Record reviewed application build source and remaining authenticated operation work
This commit is contained in:
parent
16236ef479
commit
8951d32419
17 changed files with 1115 additions and 0 deletions
|
|
@ -0,0 +1,110 @@
|
|||
# Apps Forgejo release build r1
|
||||
|
||||
This is an isolated Apps source/package proposal for NK-WP-0048-T39. The complete
|
||||
reviewed seven-path Forgejo extension was built with its frontend and embedded
|
||||
assets, then assembled into a rootless OCI image archive. Apps' deployed image,
|
||||
Helm values and existing deployment targets are unchanged. Canonical source,
|
||||
commits, registry publication and formal owner assent were not performed.
|
||||
The application profile still requires an authenticated access-engine decision;
|
||||
the local claim gate is existing-case compatibility code, not a single-PDP
|
||||
exception or final architecture acceptance. T37 and the T34 operational backend
|
||||
remain independently open.
|
||||
|
||||
`owner-source/` and `apps-release-build-source.patch` propose only build tooling,
|
||||
locked public release inputs and Make targets on Apps
|
||||
`944b30ad63ab054cc24617e374e177d34cd572da`. Upstream source is extracted only
|
||||
under `/tmp`; no second application source tree is installed in Apps. The
|
||||
existing Apps Make/tools surface invokes the real upstream `frontend`,
|
||||
`generate-backend` and `static-executable` targets. The immutable reviewed
|
||||
extension input remains patch SHA256
|
||||
`f2788b3f2bf84dbc0f94e232b6c9614a864b8123c09f9e44703d50d5e1b53257`.
|
||||
Owner source acknowledgment/integration/publication is separate.
|
||||
|
||||
The source archive, Go1.24.3 distribution and all seven reviewed source outputs
|
||||
were verified against the independent review before reuse. Its source, Go tree,
|
||||
module cache, original binary and evidence were not changed; Go/module inputs
|
||||
were mounted read-only and build caches copied into owned workspaces. Node
|
||||
v22.15.0 was downloaded from the official distribution and matched its official
|
||||
SHA256. `go.mod`, `go.sum`, `package.json` and `package-lock.json` are hash-locked;
|
||||
all 1,150 lockfile package records have public npm origins and integrity hashes.
|
||||
Both actual installations used 1,088 applicable packages with lifecycle scripts
|
||||
disabled. The decisive frontend/backend builds ran with empty HOME/config paths,
|
||||
a closed environment, read-only module input, `GOPROXY=off` and a network
|
||||
namespace without connectivity. npm cache acquisition was an explicit prior
|
||||
public-only phase; no credential store, private config, paid/model service or
|
||||
production/native endpoint was used.
|
||||
|
||||
Two separate source workspaces produced 628 byte-identical frontend asset files,
|
||||
four byte-identical generated bindata source files and the same 110,936,928-byte
|
||||
static executable:
|
||||
|
||||
`sha256:4df429454b0289c6df76d7fd95d41394ebc286191809349b2c1e655b6be494e4`
|
||||
|
||||
The actual executable exposed the implemented CLI flag and extracted every one
|
||||
of its 2,234 public/options/template files with exact source byte equality,
|
||||
including generated JS/CSS/fonts/licenses. This verification mounted **no source
|
||||
tree, asset tree, host libraries or host configuration**: only the static binary
|
||||
and an empty output directory were available in a network/PID-isolated sandbox.
|
||||
A filesystem asset fallback could not pass. ELF inspection found no dynamic
|
||||
interpreter. The retained glibc/SQLite optional `dlopen` linker diagnostic is not
|
||||
represented as a production SQLite-extension or whole-service runtime proof.
|
||||
|
||||
The pinned public build-only runtime base is official Forgejo 11.0.3-rootless,
|
||||
linux/amd64 manifest
|
||||
`sha256:41649dff5311664097d29b4d80620403f0b27e7c0eee0b8af79b132a37f3807b`
|
||||
(index `sha256:691657c7e64af7730a2e885e6d022cf16ae60724931c5392bd61838afadcaeba`).
|
||||
Its manifest/config digests were checked independently. Local Docker assembly
|
||||
used only that base, the verified executable and fixed provenance labels, with
|
||||
no RUN directives, privileged container, host/secret mount, deployment tag or
|
||||
push. Export verification checks the entire original base layer prefix,
|
||||
rootless user/entrypoint/environment/paths/volumes and exact final binary bytes.
|
||||
The final OCI image manifest is
|
||||
`sha256:9d12779f0936b9ccdbde402a9869eaad8bb91ba724d579b6c2983e8e58dabf96`;
|
||||
its config digest is
|
||||
`sha256:e9e81da43c5ea6895a95b6304337a40874e3275833be5f21fc6ffc104f79a2af`.
|
||||
Two no-cache OCI builds produced identical manifest/config and identical archive
|
||||
bytes: `sha256:e0e74653321383e133485191f0ac5af53aafb065fb5809e20ede2808cec91539`.
|
||||
These are local build outputs, not an accepted deployment selection. The final
|
||||
OCI archive was not loaded as a runtime image or published. Prototype untagged
|
||||
images are retained locally as build evidence only.
|
||||
|
||||
`evidence/` retains input/proof/output digests and local artifact paths. Large
|
||||
source/cache/binary/image artifacts remain under the recorded `/tmp` paths,
|
||||
including `/tmp/apps-forgejo-release-repro-r1/image.oci.tar`; they are not placed in
|
||||
canonical source or published. Public registry metadata/base acquisition used
|
||||
anonymous protocol access with an empty Docker config; no existing private
|
||||
credential or HOME configuration was loaded. Container assembly/export uses
|
||||
only the explicit local Unix socket. The source compiler toolchain/sysroot is
|
||||
scoped to the recorded Linux amd64 review environment; a different host/compiler
|
||||
or architecture is a different input revision, not an automatic fallback.
|
||||
|
||||
The same trial retains its predecessors and refinements. Upstream Make's
|
||||
`GOFLAGS := -v` overrode environment-only trimpath flags; the final recipe passes
|
||||
flags explicitly on Make's command line. File **and directory** timestamps are
|
||||
normalised for bindata. The initial extraction harness omitted the CLI's required
|
||||
`**` pattern; its failure is retained. Docker29's containerd image store rejected
|
||||
export by the config digest from `--iidfile`; the image build had succeeded.
|
||||
That exact prototype manifest was resolved and exported without rebuilding.
|
||||
A no-cache repeat then exposed varying COPY parent-directory timestamps. The
|
||||
BuildKit primary-source remedy is `rewrite-timestamp=true`; direct image load
|
||||
conflicts with unpack on this engine, so the final recipe directly exports OCI.
|
||||
Its image epoch is the maximum of the source epoch and rounded-up immutable base
|
||||
creation time, preserving the complete original base layer prefix. Failed repeat
|
||||
and unpack records are retained. These are recorded
|
||||
source/build refinements, not extra native trials, approvals or successes. No
|
||||
build was restarted because an observation call timed out.
|
||||
|
||||
[SECRET-INPUT-PROPOSAL.md](SECRET-INPUT-PROPOSAL.md) gives the concrete separate
|
||||
CLI/private-file/chart-helper change required to avoid runtime `--secret` argv.
|
||||
It is **not implemented or admitted** by this seven-path build. In particular,
|
||||
a new `secretFile` key alone would still trigger the current chart's automatic
|
||||
`--secret` insertion. No secret value was used in any agent/build argument.
|
||||
The actual operation/inverse, durable authenticated journal, exact persisted
|
||||
application before/post source state, all-writer exclusion and current sessions
|
||||
remain T34 work. Helm omission/rollback still does not remove persisted OAuth
|
||||
sources; image downgrade before verified application-source inverse is unsafe.
|
||||
Linked users/external logins must never be removed to force deletion.
|
||||
|
||||
See `owner-source/build/forgejo/README.md` for the exact prepare/acquire/build/
|
||||
verify/container commands and refusal behavior. This packet supplies no native
|
||||
placement, capacity, rollout, group/login probe, secret-read or authority grant.
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"two_independent_source_workspaces": true,
|
||||
"binary_byte_identical": true,
|
||||
"binary_sha256": "4df429454b0289c6df76d7fd95d41394ebc286191809349b2c1e655b6be494e4",
|
||||
"bytes": 110936928,
|
||||
"generated_bindata_sources_identical": {
|
||||
"modules/public/bindata.go": "b01dc648ebe2654648ed1d59aa5691cc9df6d6c91dcf8de53c61df5eac5159fb",
|
||||
"modules/options/bindata.go": "007db55c390fcbc4d48fffba7c5eeb5379950011b02f1784e9caa5bb32c44ec6",
|
||||
"modules/templates/bindata.go": "e2fb15b4a237bae1e8a4cf455be8a2d77e6fe5b6e803f518ba20198bb0712bb1",
|
||||
"modules/migration/bindata.go": "de07bf72d462550a31f0e00e8b4163f3b3448778eda2b35e43af5ef075aebbff"
|
||||
},
|
||||
"same_trial_refinements_not_new_native_successes": true
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"two_no_cache_OCI_builds": true,
|
||||
"identical_image_manifest_and_config": true,
|
||||
"digests": {
|
||||
"containerimage.digest": "sha256:9d12779f0936b9ccdbde402a9869eaad8bb91ba724d579b6c2983e8e58dabf96",
|
||||
"containerimage.config.digest": "sha256:e9e81da43c5ea6895a95b6304337a40874e3275833be5f21fc6ffc104f79a2af"
|
||||
},
|
||||
"oci_archive_1_sha256": "e0e74653321383e133485191f0ac5af53aafb065fb5809e20ede2808cec91539",
|
||||
"oci_archive_2_sha256": "e0e74653321383e133485191f0ac5af53aafb065fb5809e20ede2808cec91539",
|
||||
"oci_archive_bytes_identical": true,
|
||||
"source_binary_independently_reproduced": true,
|
||||
"all_original_base_layers_preserved": true,
|
||||
"no_registry_publication": true,
|
||||
"no_deployment_selection": true
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"schema": "custodian.apps-forgejo-release-build-source.v1",
|
||||
"apps_base": "944b30ad63ab054cc24617e374e177d34cd572da",
|
||||
"canonical_public_files_unchanged": {
|
||||
"Makefile": "a319e264e6f04378f6b3d2c7781860fc4bac1abdb248cffa8c26065e08f2f290",
|
||||
"helm/forgejo-values.yaml": "cf87a3dccd666bf8870619755afac4af64fc0bee77b0f0ea54718d6384b70d4f",
|
||||
"helm/forgejo-registry-values.yaml": "a38f551734843c6367448f267c7376b1aeee010927a49690fdd7c1471e0ae450"
|
||||
},
|
||||
"reviewed_patch_sha256": "f2788b3f2bf84dbc0f94e232b6c9614a864b8123c09f9e44703d50d5e1b53257",
|
||||
"reviewed_source_and_original_binary_unchanged": true,
|
||||
"earlier_packets": {
|
||||
"apps-chart-projection-r1": {
|
||||
"frozen_entries_verified": 33,
|
||||
"metadata_original_reconstructed": true
|
||||
},
|
||||
"apps-execution-backend-r1": {
|
||||
"frozen_entries_verified": 8,
|
||||
"metadata_original_reconstructed": false
|
||||
},
|
||||
"forgejo-required-claim-values-r1": {
|
||||
"frozen_entries_verified": 33,
|
||||
"metadata_original_reconstructed": false
|
||||
}
|
||||
},
|
||||
"metadata_refinement_proof": "evidence/earlier-metadata-observation.json",
|
||||
"inputs_lock_sha256": "29f329b204a2a5f72084b50d59e8445486ff4799450097c6f3908c74e87a233a",
|
||||
"owner_patch_sha256": "f0bcb2903592874d355e2a403de0c22aeda79b00070f30e7ea02b45106dd67fa",
|
||||
"owner_postimages": {
|
||||
"Makefile": "572d36e2dd3dee6321a5f6c4726f83991031672be5eb3480ae6173f8ce50ccdd",
|
||||
"build/forgejo/README.md": "c3d37b8e62a99c351b8630a31f875fb8f4afbf54ec2488460066c88148f76fa8",
|
||||
"build/forgejo/inputs.lock.json": "29f329b204a2a5f72084b50d59e8445486ff4799450097c6f3908c74e87a233a",
|
||||
"build/forgejo/required-claim-values.patch": "f2788b3f2bf84dbc0f94e232b6c9614a864b8123c09f9e44703d50d5e1b53257",
|
||||
"build/forgejo/runtime-base-config.json": "bc5a3df111729582faadebd01d126ba769e2b65d0c62f306f6bc79f4e562452b",
|
||||
"tools/forgejo-release-build.py": "6ecb2cf4bd700b6d859d70024904cee7a8dd32d8cb0d43ada92ee5279f43994e"
|
||||
},
|
||||
"exact_patch_applied_and_all_postimages_verified": true,
|
||||
"source_integration": false,
|
||||
"formal_owner_assent": false,
|
||||
"commits_or_publication": false
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"schema": "custodian.apps-forgejo-release-build-validation.v1",
|
||||
"task": "NK-WP-0048-T39 source/local build preparation",
|
||||
"full_frontend_and_embedded_static_backend": true,
|
||||
"frontend_reproduction": "evidence/frontend-reproduction.json",
|
||||
"binary_reproduction": "evidence/binary-reproduction.json",
|
||||
"bare_binary_asset_verification": "evidence/verification.json",
|
||||
"deterministic_oci_reproduction": "evidence/container-reproduction.json",
|
||||
"final_container": "evidence/container-result.json",
|
||||
"patch_apply_and_all_six_postimages_exact": true,
|
||||
"canonical_deployed_defaults_unchanged": true,
|
||||
"independent_review_source_and_binary_unchanged": true,
|
||||
"prior_failures_preserved": true,
|
||||
"secret_input_proposal_implemented": false,
|
||||
"T37_architecture_acceptance": false,
|
||||
"T34_native_backend_journal_exclusion_inverse_sessions": false,
|
||||
"authenticated_access_engine_decision_still_required": true,
|
||||
"native_or_credential_or_paid_model_calls": false,
|
||||
"deployment_selection_or_registry_publication": false,
|
||||
"formal_owner_assent": false
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"recorded_at": "2026-10-17T22:03:08.633215+00:00",
|
||||
"same_trial": true,
|
||||
"apps_base": "git:944b30ad63ab054cc24617e374e177d34cd572da",
|
||||
"predecessor_patch_sha256": "sha256:f0bcb2903592874d355e2a403de0c22aeda79b00070f30e7ea02b45106dd67fa",
|
||||
"patch_sha256": "sha256:b7ad8f8fd908532800f4e7eb0f7ad85d77e21a0b729cb5115ade3d5fe3e4acd8",
|
||||
"owner_postimages": {
|
||||
"Makefile": "sha256:572d36e2dd3dee6321a5f6c4726f83991031672be5eb3480ae6173f8ce50ccdd",
|
||||
"build/forgejo/README.md": "sha256:c3d37b8e62a99c351b8630a31f875fb8f4afbf54ec2488460066c88148f76fa8",
|
||||
"build/forgejo/inputs.lock.json": "sha256:29f329b204a2a5f72084b50d59e8445486ff4799450097c6f3908c74e87a233a",
|
||||
"build/forgejo/required-claim-values.patch": "sha256:f2788b3f2bf84dbc0f94e232b6c9614a864b8123c09f9e44703d50d5e1b53257",
|
||||
"build/forgejo/runtime-base-config.json": "sha256:bc5a3df111729582faadebd01d126ba769e2b65d0c62f306f6bc79f4e562452b",
|
||||
"tools/forgejo-release-build.py": "sha256:7e28d9bd5adefaece96eb1d31a23e128ec8f448958e45d22467bf7acf476a9ba"
|
||||
},
|
||||
"refinement": "Only --unshare-pid added in build sandbox. Original full build/OCI proof and adverse process-visibility canary remain historical evidence.",
|
||||
"source_code_changed": [
|
||||
"tools/forgejo-release-build.py:sandbox"
|
||||
],
|
||||
"patch_apply_and_postimages_verified": true,
|
||||
"scratch": "/tmp/apps-build-r2-patch-verified-qpaw0ol9",
|
||||
"actual_full_r2_build_performed": false,
|
||||
"existing_full_build_proof": "../apps-forgejo-release-build-r1/evidence/",
|
||||
"canonical_edits": false,
|
||||
"native_actions": false,
|
||||
"review_status": "pending exact namespace-fix review",
|
||||
"patch_generation_refinement": {
|
||||
"failed_patch_sha256": "sha256:64c86ac86cf78715535b096cbf47204586a5c26b7e9c993cce2c136cb5ae2cee",
|
||||
"outcome": "Patch application returned success but exact postimage guard refused runtime-base-config.json; generated patch lacked no-final-newline marker and appended next diff header. No candidate or canonical source changed.",
|
||||
"correction": "Derived exact original already-verified six-path patch, changed only existing sandbox line; all six postimages byte-identical to intended outputs."
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"public_synthetic_fixture_only": true,
|
||||
"outer_PID_and_network_namespace_prevent_real_host_visibility": true,
|
||||
"shipped_sandbox": {
|
||||
"returncode": 1,
|
||||
"stdout": "",
|
||||
"stderr": "Traceback (most recent call last):\n File \"<string>\", line 1, in <module>\n File \"/usr/lib/python3.12/pathlib.py\", line 862, in exists\n self.stat(follow_symlinks=follow_symlinks)\n File \"/usr/lib/python3.12/pathlib.py\", line 842, in stat\n return os.stat(self, follow_symlinks=follow_symlinks)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nPermissionError: [Errno 13] Permission denied: '/proc/2/root/tmp/review/outside-build-workspace-synthetic.txt'\n"
|
||||
},
|
||||
"same_command_with_only_unshare_pid_added": {
|
||||
"returncode": 0,
|
||||
"stdout": "False\nDENIED\n",
|
||||
"stderr": ""
|
||||
},
|
||||
"shipped_sandbox_proc_parent_root_escape": false,
|
||||
"unshare_pid_control_denies_fixture": true,
|
||||
"shipped_sandbox_host_process_cmdline": {
|
||||
"returncode": 0,
|
||||
"stdout": "b'/usr/bin/python3\\x00-I\\x00-c\\x00import sys;sys.stdin.read()\\x00PUBLIC-SYNTHETIC-ARGV-CANARY\\x00'\n",
|
||||
"stderr": ""
|
||||
},
|
||||
"with_unshare_pid_host_process_cmdline": {
|
||||
"returncode": 0,
|
||||
"stdout": "DENIED\n",
|
||||
"stderr": ""
|
||||
},
|
||||
"outside_process_argv_visible": true,
|
||||
"unshare_pid_control_denies_argv": true,
|
||||
"helper_terminal": 0
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
"""Synthetic-only test of the shipped sandbox's proc visibility inside outer PID isolation."""
|
||||
import importlib.util,json,os,subprocess
|
||||
from pathlib import Path
|
||||
out=Path('/tmp/review')
|
||||
fixture=out/'outside-build-workspace-synthetic.txt'
|
||||
fixture.write_text('PUBLIC-SYNTHETIC-BOUNDARY-CANARY\n')
|
||||
work=out/'boundary-work';(work/'source').mkdir(parents=True);(work/'cache').mkdir()
|
||||
spec=importlib.util.spec_from_file_location('recipe','/proposal/owner-source/tools/forgejo-release-build.py')
|
||||
m=importlib.util.module_from_spec(spec);spec.loader.exec_module(m)
|
||||
env={'PATH':'/usr/bin:/bin','HOME':str(work/'home'),'GOMODCACHE':str(work/'cache')}
|
||||
base=m.sandbox(work,env)
|
||||
target='/proc/'+str(os.getpid())+'/root'+str(fixture)
|
||||
command=['/usr/bin/python3','-I','-c','import pathlib,sys; p=pathlib.Path(sys.argv[1]); print(p.exists()); print(p.read_text() if p.exists() else "DENIED")',target]
|
||||
def run(args):
|
||||
p=subprocess.run(args,env={'PATH':'/usr/bin:/bin','HOME':'/tmp/home'},capture_output=True,text=True)
|
||||
return {'returncode':p.returncode,'stdout':p.stdout,'stderr':p.stderr}
|
||||
original=run(base+command)
|
||||
corrected=run(base[:1]+['--unshare-pid']+base[1:]+command)
|
||||
helper=subprocess.Popen(['/usr/bin/python3','-I','-c','import sys;sys.stdin.read()',
|
||||
'PUBLIC-SYNTHETIC-ARGV-CANARY'],stdin=subprocess.PIPE,
|
||||
env={'PATH':'/usr/bin:/bin','HOME':'/tmp/home'})
|
||||
try:
|
||||
cmdline=['/usr/bin/python3','-I','-c',
|
||||
'import pathlib,sys; p=pathlib.Path(sys.argv[1]); print(p.read_bytes() if p.exists() else "DENIED")',
|
||||
'/proc/'+str(helper.pid)+'/cmdline']
|
||||
argv_original=run(base+cmdline)
|
||||
argv_corrected=run(base[:1]+['--unshare-pid']+base[1:]+cmdline)
|
||||
finally:
|
||||
helper.stdin.close()
|
||||
helper.wait(timeout=10)
|
||||
result={'public_synthetic_fixture_only':True,'outer_PID_and_network_namespace_prevent_real_host_visibility':True,
|
||||
'shipped_sandbox':original,'same_command_with_only_unshare_pid_added':corrected,
|
||||
'shipped_sandbox_proc_parent_root_escape': 'PUBLIC-SYNTHETIC-BOUNDARY-CANARY' in original['stdout'],
|
||||
'unshare_pid_control_denies_fixture':'PUBLIC-SYNTHETIC-BOUNDARY-CANARY' not in corrected['stdout'],
|
||||
'shipped_sandbox_host_process_cmdline':argv_original,
|
||||
'with_unshare_pid_host_process_cmdline':argv_corrected,
|
||||
'outside_process_argv_visible':'PUBLIC-SYNTHETIC-ARGV-CANARY' in argv_original['stdout'],
|
||||
'unshare_pid_control_denies_argv':'PUBLIC-SYNTHETIC-ARGV-CANARY' not in argv_corrected['stdout'],
|
||||
'helper_terminal':helper.returncode}
|
||||
(out/'proc-boundary-result.json').write_text(json.dumps(result,indent=2)+'\n')
|
||||
print(json.dumps(result,indent=2))
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
"schema": "custodian.apps-release-independent-review.v1",
|
||||
"reviewed_on": "2026-10-18",
|
||||
"verdict": "changes-required",
|
||||
"source_integration_accepted": false,
|
||||
"candidate_patch_sha256": "f0bcb2903592874d355e2a403de0c22aeda79b00070f30e7ea02b45106dd67fa",
|
||||
"candidate_map_sha256": "ec499038fa9a1e612bb81ed63bd67dad2ca52a178bb7bcb89a33bb64832880bb",
|
||||
"findings": [
|
||||
{
|
||||
"id": "APPSBUILD-R1-F01",
|
||||
"severity": "medium",
|
||||
"blocks_source_integration": true,
|
||||
"path": "tools/forgejo-release-build.py",
|
||||
"line": 46,
|
||||
"problem": "Build sandbox exposes unrelated host process command lines through /proc because it does not create a PID namespace.",
|
||||
"evidence": "proc-boundary-result.json: outside_process_argv_visible=true; unshare_pid_control_denies_argv=true",
|
||||
"scope": "Actual synthetic unrelated argv read, not a demonstrated host filesystem escape or real credential exposure.",
|
||||
"requested_correction": "Add --unshare-pid to sandbox(); preserve r1 and exact adverse evidence, publish separate revised source packet."
|
||||
}
|
||||
],
|
||||
"frozen_entries_verified": 71,
|
||||
"exact_six_path_pre_postimage_check": true,
|
||||
"accepted_prior_backend_source_review_bound": true,
|
||||
"fresh_bare_binary_verifier": "PASS (2234 files exact, new CLI, no ELF interpreter)",
|
||||
"seven_adverse_input_controls": "PASS",
|
||||
"retained_full_build_artifacts_rehashed": "PASS (2 workspaces, 628 frontend files each, 4 bindata outputs each, exact same binary)",
|
||||
"OCI_independent_offline_content_and_provenance_checks": "PASS (all descriptors, blob hashes, diff_ids, original base prefix, rootless config, labels, binary, mode, timestamps)",
|
||||
"full_build_repeated_by_reviewer": false,
|
||||
"OCI_build_repeated_by_reviewer": false,
|
||||
"prior_artifacts_represent_original_r1_profile": true,
|
||||
"reviewer_failed_outcome_preserved": "offline-attempt1.json/.log; offline-results-attempt1.json; review-offline-attempt1.py; upper-bound timestamp assertion corrected only in reviewer harness",
|
||||
"canonical_Apps_unchanged": "944b30ad63ab054cc24617e374e177d34cd572da",
|
||||
"candidate_unchanged": true,
|
||||
"reviewer_writes": "Only this review packet and private /tmp public-fixture workspaces; root original eight dirty paths not touched.",
|
||||
"network_native_registry_docker_credential_model_operations": false,
|
||||
"formal_owner_assent": false,
|
||||
"architecture_acceptance": false,
|
||||
"deployment_authority": false,
|
||||
"existing_operational_gaps": [
|
||||
"authenticated Access Engine decision",
|
||||
"private runtime secret input (not implemented)",
|
||||
"owner integration and image admission/publication",
|
||||
"exact type/case/descriptor re-freeze",
|
||||
"current operation and inverse sessions",
|
||||
"durable authenticated journal",
|
||||
"authoritative persisted application before/post/current state",
|
||||
"all release/application writer exclusion",
|
||||
"browser/group/login proofs",
|
||||
"capacity and rollout"
|
||||
],
|
||||
"execution_status": {
|
||||
"all_owned_handles_terminal": true,
|
||||
"live_handles": [],
|
||||
"helper_terminal_returncode": 0,
|
||||
"native_trial_started": false
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
{
|
||||
"APPSBUILD-R1-F01_closed_for_exact_r2": true,
|
||||
"exact_refinement": {
|
||||
"old_review_and_inputs_preserved": true,
|
||||
"only_change": "sandbox adds --unshare-pid",
|
||||
"six_paths": 6,
|
||||
"unchanged_locks_archives_patch_release_and_runtime_base": true
|
||||
},
|
||||
"full_r2_build_or_image_build_performed": false,
|
||||
"namespace_fix": {
|
||||
"r1": {
|
||||
"argv": [
|
||||
"bwrap",
|
||||
"--unshare-net",
|
||||
"--ro-bind",
|
||||
"/usr",
|
||||
"/usr",
|
||||
"--ro-bind",
|
||||
"/lib",
|
||||
"/lib",
|
||||
"--ro-bind",
|
||||
"/lib64",
|
||||
"/lib64",
|
||||
"--symlink",
|
||||
"usr/bin",
|
||||
"/bin",
|
||||
"--proc",
|
||||
"/proc",
|
||||
"--dev",
|
||||
"/dev",
|
||||
"--tmpfs",
|
||||
"/tmp",
|
||||
"--bind",
|
||||
"/tmp/review/sandbox-work",
|
||||
"/tmp/review/sandbox-work",
|
||||
"--ro-bind",
|
||||
"/tmp/review/sandbox-work/cache",
|
||||
"/tmp/review/sandbox-work/cache",
|
||||
"--chdir",
|
||||
"/tmp/review/sandbox-work/source",
|
||||
"--",
|
||||
"env",
|
||||
"-i",
|
||||
"PATH=/usr/bin:/bin",
|
||||
"HOME=/tmp/review/sandbox-work/empty-home",
|
||||
"GOMODCACHE=/tmp/review/sandbox-work/cache",
|
||||
"LC_ALL=C",
|
||||
"/usr/bin/python3",
|
||||
"-I",
|
||||
"-c",
|
||||
"import pathlib,sys,os,json; p=pathlib.Path(sys.argv[1]); print(json.dumps({\"parent_argv\": p.read_text() if p.exists() else \"DENIED\", \"self_pid\":os.getpid(),\"pid_namespace\":os.readlink(\"/proc/self/ns/pid\"),\"cwd\":os.getcwd(),\"host_home_present\":pathlib.Path(\"/home/worsch\").exists(),\"docker_socket_present\":pathlib.Path(\"/var/run/docker.sock\").exists(),\"environment\":dict(os.environ)}))",
|
||||
"/proc/5/cmdline"
|
||||
],
|
||||
"result": {
|
||||
"cwd": "/tmp/review/sandbox-work/source",
|
||||
"docker_socket_present": false,
|
||||
"environment": {
|
||||
"GOMODCACHE": "/tmp/review/sandbox-work/cache",
|
||||
"HOME": "/tmp/review/sandbox-work/empty-home",
|
||||
"LC_ALL": "C",
|
||||
"PATH": "/usr/bin:/bin"
|
||||
},
|
||||
"host_home_present": false,
|
||||
"parent_argv": "/usr/bin/python3\u0000-I\u0000-c\u0000import sys;sys.stdin.read()\u0000PUBLIC-R2-SYNTHETIC-ARGV-CANARY\u0000",
|
||||
"pid_namespace": "pid:[4026532379]",
|
||||
"self_pid": 7
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"argv": [
|
||||
"bwrap",
|
||||
"--unshare-net",
|
||||
"--unshare-pid",
|
||||
"--ro-bind",
|
||||
"/usr",
|
||||
"/usr",
|
||||
"--ro-bind",
|
||||
"/lib",
|
||||
"/lib",
|
||||
"--ro-bind",
|
||||
"/lib64",
|
||||
"/lib64",
|
||||
"--symlink",
|
||||
"usr/bin",
|
||||
"/bin",
|
||||
"--proc",
|
||||
"/proc",
|
||||
"--dev",
|
||||
"/dev",
|
||||
"--tmpfs",
|
||||
"/tmp",
|
||||
"--bind",
|
||||
"/tmp/review/sandbox-work",
|
||||
"/tmp/review/sandbox-work",
|
||||
"--ro-bind",
|
||||
"/tmp/review/sandbox-work/cache",
|
||||
"/tmp/review/sandbox-work/cache",
|
||||
"--chdir",
|
||||
"/tmp/review/sandbox-work/source",
|
||||
"--",
|
||||
"env",
|
||||
"-i",
|
||||
"PATH=/usr/bin:/bin",
|
||||
"HOME=/tmp/review/sandbox-work/empty-home",
|
||||
"GOMODCACHE=/tmp/review/sandbox-work/cache",
|
||||
"LC_ALL=C",
|
||||
"/usr/bin/python3",
|
||||
"-I",
|
||||
"-c",
|
||||
"import pathlib,sys,os,json; p=pathlib.Path(sys.argv[1]); print(json.dumps({\"parent_argv\": p.read_text() if p.exists() else \"DENIED\", \"self_pid\":os.getpid(),\"pid_namespace\":os.readlink(\"/proc/self/ns/pid\"),\"cwd\":os.getcwd(),\"host_home_present\":pathlib.Path(\"/home/worsch\").exists(),\"docker_socket_present\":pathlib.Path(\"/var/run/docker.sock\").exists(),\"environment\":dict(os.environ)}))",
|
||||
"/proc/5/cmdline"
|
||||
],
|
||||
"result": {
|
||||
"cwd": "/tmp/review/sandbox-work/source",
|
||||
"docker_socket_present": false,
|
||||
"environment": {
|
||||
"GOMODCACHE": "/tmp/review/sandbox-work/cache",
|
||||
"HOME": "/tmp/review/sandbox-work/empty-home",
|
||||
"LC_ALL": "C",
|
||||
"PATH": "/usr/bin:/bin"
|
||||
},
|
||||
"host_home_present": false,
|
||||
"parent_argv": "DENIED",
|
||||
"pid_namespace": "pid:[4026532441]",
|
||||
"self_pid": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"patch_exact_six_postimages": true,
|
||||
"r1_artifact_evidence_retains_r1_profile": true,
|
||||
"synthetic_helper_terminal_returncode": 0
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
"schema": "custodian.apps-release-independent-review.v1",
|
||||
"reviewed_on": "2026-10-18",
|
||||
"verdict": "accept",
|
||||
"source_integration_accepted": true,
|
||||
"candidate_patch_sha256": "b7ad8f8fd908532800f4e7eb0f7ad85d77e21a0b729cb5115ade3d5fe3e4acd8",
|
||||
"candidate_source_refinement_sha256": "1e96b866284908299b6363c0ddd1363181bd8513ae63eb178967f636de008972",
|
||||
"predecessor_review": "../apps-release-independent-review-r1/review.json",
|
||||
"predecessor_review_sha256": "df2c23df953e1d4c10bd3abd7aea350cc33d8bbfdb2a99d92a436feba0946f73",
|
||||
"predecessor_review_map_sha256": "9a2266ffa638ce771a5cc014e93b53c8e465270d351c502cf42c9c586409f7c9",
|
||||
"same_trial": true,
|
||||
"findings": [],
|
||||
"closed_findings": [
|
||||
{
|
||||
"id": "APPSBUILD-R1-F01",
|
||||
"correction": "Only --unshare-pid added to exact build sandbox",
|
||||
"evidence": "results.json: exact r1 synthetic outside-process argv readable, exact r2 returns DENIED, new PID namespace inode verified."
|
||||
}
|
||||
],
|
||||
"exact_patch_pre_postimages": true,
|
||||
"owner_postimages": {
|
||||
"Makefile": "sha256:572d36e2dd3dee6321a5f6c4726f83991031672be5eb3480ae6173f8ce50ccdd",
|
||||
"build/forgejo/README.md": "sha256:c3d37b8e62a99c351b8630a31f875fb8f4afbf54ec2488460066c88148f76fa8",
|
||||
"build/forgejo/inputs.lock.json": "sha256:29f329b204a2a5f72084b50d59e8445486ff4799450097c6f3908c74e87a233a",
|
||||
"build/forgejo/required-claim-values.patch": "sha256:f2788b3f2bf84dbc0f94e232b6c9614a864b8123c09f9e44703d50d5e1b53257",
|
||||
"build/forgejo/runtime-base-config.json": "sha256:bc5a3df111729582faadebd01d126ba769e2b65d0c62f306f6bc79f4e562452b",
|
||||
"tools/forgejo-release-build.py": "sha256:7e28d9bd5adefaece96eb1d31a23e128ec8f448958e45d22467bf7acf476a9ba"
|
||||
},
|
||||
"only_source_delta": "tools/forgejo-release-build.py:sandbox adds --unshare-pid",
|
||||
"build_inputs_and_commands_unchanged": true,
|
||||
"prior_r1_source_and_review_maps_reverified": true,
|
||||
"prior_full_frontend_bindata_binary_OCI_proof": "Frozen r1 artifacts and profile only; retained independent byte/content verification in r1 review.",
|
||||
"full_r2_build_performed": false,
|
||||
"full_r2_image_build_performed": false,
|
||||
"r2_binary_or_image_reproduction_claimed": false,
|
||||
"expensive_rebuild_required_for_bounded_source_acceptance": false,
|
||||
"reviewer_failure_preserved": "execution-attempt1.json, namespace-review-attempt1.log, review-namespace-refinement-attempt1.py: incorrect PID1 child assertion; corrected to namespace inode inequality. No candidate change.",
|
||||
"candidate_or_canonical_changed_by_reviewer": false,
|
||||
"formal_owner_assent": false,
|
||||
"architecture_acceptance": false,
|
||||
"image_admission": false,
|
||||
"deployment_authority": false,
|
||||
"existing_operational_gaps_inherited": "../apps-release-independent-review-r1/review.json:existing_operational_gaps (no gate added or waived)",
|
||||
"network_native_docker_registry_credential_model_operations": false,
|
||||
"execution_status": {
|
||||
"all_owned_handles_terminal": true,
|
||||
"live_handles": [],
|
||||
"synthetic_helper_returncode": 0
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
"""Integrate only exact independently accepted build source and owner tasks."""
|
||||
from pathlib import Path
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
ROOT = Path('/home/worsch/railiance-apps')
|
||||
PACKET = HERE.parent / 'apps-forgejo-release-build-r2'
|
||||
OLD_PACKET = HERE.parent / 'apps-forgejo-release-build-r1'
|
||||
BASE = '944b30ad63ab054cc24617e374e177d34cd572da'
|
||||
PLAN = 'workplans/RAPPS-WP-0016-forgejo-netkingdom-login.md'
|
||||
|
||||
|
||||
def sha(data):
|
||||
return hashlib.sha256(data).hexdigest()
|
||||
|
||||
|
||||
def git(*args):
|
||||
return subprocess.check_output(['git', '-C', str(ROOT), *args],
|
||||
stderr=subprocess.PIPE, timeout=45).decode().strip()
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--review', type=Path, required=True)
|
||||
parser.add_argument('--review-sha256', required=True)
|
||||
args = parser.parse_args()
|
||||
assert sha(args.review.read_bytes()) == args.review_sha256.removeprefix('sha256:')
|
||||
review = json.loads(args.review.read_text())
|
||||
assert review['source_integration_accepted'] is True
|
||||
assert review['verdict'] == 'accept'
|
||||
refinement = json.loads((PACKET / 'source-refinement.json').read_text())
|
||||
assert sha((PACKET / 'source-refinement.json').read_bytes()) == review['candidate_source_refinement_sha256'].removeprefix('sha256:')
|
||||
assert refinement['owner_postimages'] == review['owner_postimages']
|
||||
patch_hash = sha((PACKET / 'apps-release-build-source.patch').read_bytes())
|
||||
assert 'sha256:' + patch_hash == refinement['patch_sha256']
|
||||
assert review['candidate_patch_sha256'].removeprefix('sha256:') == patch_hash
|
||||
assert git('rev-parse', 'HEAD') == BASE
|
||||
assert git('ls-remote', 'origin', 'refs/heads/main').split()[0] == BASE
|
||||
assert set(git('diff', '--name-only', 'HEAD').splitlines()) <= {'.custodian-brief.md', 'WORK-RECORDS.md'}
|
||||
originals = {n: {'worktree_sha256': sha((ROOT / n).read_bytes()),
|
||||
'index': git('ls-files', '--stage', '--', n)}
|
||||
for n in ('.custodian-brief.md', 'WORK-RECORDS.md') if (ROOT / n).exists()}
|
||||
inventory = json.loads((OLD_PACKET / 'source-inventory.json').read_text())
|
||||
for n, expected in inventory['canonical_public_files_unchanged'].items():
|
||||
assert sha((ROOT / n).read_bytes()) == expected, n
|
||||
for n, expected in refinement['owner_postimages'].items():
|
||||
assert sha((PACKET / 'owner-source' / n).read_bytes()) == expected.removeprefix('sha256:'), n
|
||||
if n == 'Makefile':
|
||||
assert (ROOT / n).read_bytes() == (OLD_PACKET / 'preimages' / n).read_bytes()
|
||||
else:
|
||||
assert not (ROOT / n).exists(), n
|
||||
assert (ROOT / PLAN).read_bytes() == (HERE / 'preimage.md').read_bytes()
|
||||
plans = {str(p.relative_to(ROOT)): sha(p.read_bytes()) for p in (ROOT / 'workplans').rglob('*.md')}
|
||||
before_blocks = re.findall(r'```task\n.*?```', (ROOT / PLAN).read_text(), re.S)
|
||||
candidate = (HERE / 'workplan.md').read_text()
|
||||
assert len(before_blocks) == 5 and all(b in candidate for b in before_blocks)
|
||||
sys.path.insert(0, '/home/worsch/repo-manager/src')
|
||||
from repo_manager.identifiers import ensure_missing_work_record_identifiers
|
||||
preview = ensure_missing_work_record_identifiers(ROOT, execute=False)
|
||||
assert preview['ok'] and not preview['assignments'] and not preview['files_changed']
|
||||
for n in refinement['owner_postimages']:
|
||||
target = ROOT / n
|
||||
target.parent.mkdir(parents=True, exist_ok=True)
|
||||
target.write_bytes((PACKET / 'owner-source' / n).read_bytes())
|
||||
(ROOT / PLAN).write_text(candidate)
|
||||
preview = ensure_missing_work_record_identifiers(ROOT, execute=False)
|
||||
(HERE / 'identifier-preview.json').write_text(json.dumps(preview, indent=2) + '\n')
|
||||
assert preview['ok'] and preview['files_changed'] == [PLAN] and len(preview['assignments']) == 4
|
||||
assigned = ensure_missing_work_record_identifiers(ROOT, execute=True)
|
||||
(HERE / 'identifier-assignment.json').write_text(json.dumps(assigned, indent=2) + '\n')
|
||||
assert assigned['ok'] and assigned['files_changed'] == [PLAN]
|
||||
for n, expected in plans.items():
|
||||
if n != PLAN:
|
||||
assert sha((ROOT / n).read_bytes()) == expected, n
|
||||
for n, state in originals.items():
|
||||
assert sha((ROOT / n).read_bytes()) == state['worktree_sha256']
|
||||
assert git('ls-files', '--stage', '--', n) == state['index']
|
||||
assert all(b in (ROOT / PLAN).read_text() for b in before_blocks)
|
||||
files = [{'path': n, 'sha256': sha((ROOT / n).read_bytes())}
|
||||
for n in [*refinement['owner_postimages'], PLAN]]
|
||||
cfg = {'owner': 'railiance-apps', 'base_revision': BASE,
|
||||
'message': 'Add pinned Forgejo release build path and track operational integration', 'files': files}
|
||||
(HERE / 'publication-inputs.json').write_text(json.dumps(cfg, indent=2) + '\n')
|
||||
(HERE / 'source-application.json').write_text(json.dumps({
|
||||
'base': 'git:' + BASE, 'review_sha256': 'sha256:' + sha(args.review.read_bytes()),
|
||||
'patch_sha256': 'sha256:' + patch_hash, 'files': files,
|
||||
'original_task_blocks_preserved': len(before_blocks), 'other_workplans_preserved': len(plans) - 1,
|
||||
'unrelated_state': originals, 'native_actions': False,
|
||||
'image_values_and_registry_values_unchanged': True,
|
||||
'formal_owner_assent': False}, indent=2) + '\n')
|
||||
print(json.dumps({'status': 'source_applied', 'files': len(files), 'new_task_ids': 4,
|
||||
'original_task_blocks_preserved': 5, 'native_actions': False}))
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
{
|
||||
"schema": "repo-manager.identifier-assignment.v1",
|
||||
"ok": true,
|
||||
"executed": true,
|
||||
"repo": "railiance-apps",
|
||||
"namespace": "helixforge",
|
||||
"assignments": [
|
||||
{
|
||||
"kind": "task",
|
||||
"record_id": "RAPPS-WP-0016-T06",
|
||||
"uuid": "08ab8921-7801-5309-b84b-bc2a3ceea1e4",
|
||||
"path": "workplans/RAPPS-WP-0016-forgejo-netkingdom-login.md"
|
||||
},
|
||||
{
|
||||
"kind": "task",
|
||||
"record_id": "RAPPS-WP-0016-T07",
|
||||
"uuid": "786d6584-6db1-5a10-9324-d7b94db0df94",
|
||||
"path": "workplans/RAPPS-WP-0016-forgejo-netkingdom-login.md"
|
||||
},
|
||||
{
|
||||
"kind": "task",
|
||||
"record_id": "RAPPS-WP-0016-T08",
|
||||
"uuid": "4ab8a5e7-ab32-5ee2-aaf2-6da246d1b0c8",
|
||||
"path": "workplans/RAPPS-WP-0016-forgejo-netkingdom-login.md"
|
||||
},
|
||||
{
|
||||
"kind": "task",
|
||||
"record_id": "RAPPS-WP-0016-T09",
|
||||
"uuid": "d3804638-c73d-5b9f-a456-4262f62f9e6b",
|
||||
"path": "workplans/RAPPS-WP-0016-forgejo-netkingdom-login.md"
|
||||
}
|
||||
],
|
||||
"historical_invalid_identifiers": [
|
||||
{
|
||||
"kind": "task",
|
||||
"id": "RAILIANCE-WP-0004-I01",
|
||||
"source": "workplans/archived/260702-railiance-apps-WP-0004-app-deployment-improvements.md#task-block-1"
|
||||
},
|
||||
{
|
||||
"kind": "task",
|
||||
"id": "RAILIANCE-WP-0004-I02",
|
||||
"source": "workplans/archived/260702-railiance-apps-WP-0004-app-deployment-improvements.md#task-block-2"
|
||||
},
|
||||
{
|
||||
"kind": "task",
|
||||
"id": "RAILIANCE-WP-0004-I03",
|
||||
"source": "workplans/archived/260702-railiance-apps-WP-0004-app-deployment-improvements.md#task-block-3"
|
||||
},
|
||||
{
|
||||
"kind": "task",
|
||||
"id": "RAILIANCE-WP-0004-I04",
|
||||
"source": "workplans/archived/260702-railiance-apps-WP-0004-app-deployment-improvements.md#task-block-4"
|
||||
},
|
||||
{
|
||||
"kind": "task",
|
||||
"id": "RAILIANCE-WP-0004-I05",
|
||||
"source": "workplans/archived/260702-railiance-apps-WP-0004-app-deployment-improvements.md#task-block-5"
|
||||
},
|
||||
{
|
||||
"kind": "task",
|
||||
"id": "RAILIANCE-WP-0004-I06",
|
||||
"source": "workplans/archived/260702-railiance-apps-WP-0004-app-deployment-improvements.md#task-block-6"
|
||||
},
|
||||
{
|
||||
"kind": "task",
|
||||
"id": "RAILIANCE-WP-0004-I07",
|
||||
"source": "workplans/archived/260702-railiance-apps-WP-0004-app-deployment-improvements.md#task-block-7"
|
||||
}
|
||||
],
|
||||
"historical_identity_collisions": [],
|
||||
"files_changed": [
|
||||
"workplans/RAPPS-WP-0016-forgejo-netkingdom-login.md"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
"base": "git:944b30ad63ab054cc24617e374e177d34cd572da",
|
||||
"review_sha256": "sha256:6f016d53a7ec9ece2f9da9686e76127c52d17066f2b3d371628832ac9537ac5c",
|
||||
"patch_sha256": "sha256:b7ad8f8fd908532800f4e7eb0f7ad85d77e21a0b729cb5115ade3d5fe3e4acd8",
|
||||
"files": [
|
||||
{
|
||||
"path": "Makefile",
|
||||
"sha256": "572d36e2dd3dee6321a5f6c4726f83991031672be5eb3480ae6173f8ce50ccdd"
|
||||
},
|
||||
{
|
||||
"path": "build/forgejo/README.md",
|
||||
"sha256": "c3d37b8e62a99c351b8630a31f875fb8f4afbf54ec2488460066c88148f76fa8"
|
||||
},
|
||||
{
|
||||
"path": "build/forgejo/inputs.lock.json",
|
||||
"sha256": "29f329b204a2a5f72084b50d59e8445486ff4799450097c6f3908c74e87a233a"
|
||||
},
|
||||
{
|
||||
"path": "build/forgejo/required-claim-values.patch",
|
||||
"sha256": "f2788b3f2bf84dbc0f94e232b6c9614a864b8123c09f9e44703d50d5e1b53257"
|
||||
},
|
||||
{
|
||||
"path": "build/forgejo/runtime-base-config.json",
|
||||
"sha256": "bc5a3df111729582faadebd01d126ba769e2b65d0c62f306f6bc79f4e562452b"
|
||||
},
|
||||
{
|
||||
"path": "tools/forgejo-release-build.py",
|
||||
"sha256": "7e28d9bd5adefaece96eb1d31a23e128ec8f448958e45d22467bf7acf476a9ba"
|
||||
},
|
||||
{
|
||||
"path": "workplans/RAPPS-WP-0016-forgejo-netkingdom-login.md",
|
||||
"sha256": "0ac8db087247bf980339ef8661a26eeb817af82391e3e85038be773fe3c6fb3a"
|
||||
}
|
||||
],
|
||||
"original_task_blocks_preserved": 5,
|
||||
"other_workplans_preserved": 19,
|
||||
"unrelated_state": {
|
||||
".custodian-brief.md": {
|
||||
"worktree_sha256": "07f96d4120b25a046a5a82a89d2d1d1c77cad380a80772a6fc0d024da2f0c4d4",
|
||||
"index": "100644 1f9b6fae4362945f96aa9a2a9647be9c83d8296a 0\t.custodian-brief.md"
|
||||
},
|
||||
"WORK-RECORDS.md": {
|
||||
"worktree_sha256": "5a426a12d26721d4839461cf3c0285b198aafe332c3152d0744e06f0ed15e010",
|
||||
"index": "100644 89c6d25cfe29035a2e0ad71113c31b89338b0cc3 0\tWORK-RECORDS.md"
|
||||
}
|
||||
},
|
||||
"native_actions": false,
|
||||
"image_values_and_registry_values_unchanged": true,
|
||||
"formal_owner_assent": false
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"status": "verified",
|
||||
"source_commit": "git:c29408ae6747158a639dc876e6d7492680675658",
|
||||
"instance": "primary/railiance01",
|
||||
"task_bindings": [
|
||||
{
|
||||
"record_id": "RAPPS-WP-0016-T01",
|
||||
"uuid": "98004ed0-83e6-5f6e-9b18-15b8b2aec2e7",
|
||||
"status": "done"
|
||||
},
|
||||
{
|
||||
"record_id": "RAPPS-WP-0016-T02",
|
||||
"uuid": "13cd3aec-c87d-5d3f-a421-39d8ff131edd",
|
||||
"status": "wait"
|
||||
},
|
||||
{
|
||||
"record_id": "RAPPS-WP-0016-T03",
|
||||
"uuid": "81f072aa-c316-511e-a2cd-21dd1b1d0a00",
|
||||
"status": "wait"
|
||||
},
|
||||
{
|
||||
"record_id": "RAPPS-WP-0016-T04",
|
||||
"uuid": "32c54737-c40f-5fde-9b91-163f8dcb0068",
|
||||
"status": "wait"
|
||||
},
|
||||
{
|
||||
"record_id": "RAPPS-WP-0016-T05",
|
||||
"uuid": "728786c9-f1f9-5983-a6a4-dea21faf67f5",
|
||||
"status": "wait"
|
||||
},
|
||||
{
|
||||
"record_id": "RAPPS-WP-0016-T06",
|
||||
"uuid": "08ab8921-7801-5309-b84b-bc2a3ceea1e4",
|
||||
"status": "done"
|
||||
},
|
||||
{
|
||||
"record_id": "RAPPS-WP-0016-T07",
|
||||
"uuid": "786d6584-6db1-5a10-9324-d7b94db0df94",
|
||||
"status": "progress"
|
||||
},
|
||||
{
|
||||
"record_id": "RAPPS-WP-0016-T08",
|
||||
"uuid": "4ab8a5e7-ab32-5ee2-aaf2-6da246d1b0c8",
|
||||
"status": "progress"
|
||||
},
|
||||
{
|
||||
"record_id": "RAPPS-WP-0016-T09",
|
||||
"uuid": "d3804638-c73d-5b9f-a456-4262f62f9e6b",
|
||||
"status": "todo"
|
||||
}
|
||||
],
|
||||
"original_five_task_blocks_preserved": true,
|
||||
"reviewed_build_postimages_match": true,
|
||||
"native_changes": false
|
||||
}
|
||||
|
|
@ -0,0 +1,259 @@
|
|||
---
|
||||
id: RAPPS-WP-0016
|
||||
type: workplan
|
||||
title: "Forgejo sign-in through NetKingdom, before the forge closes"
|
||||
domain: infotech
|
||||
repo: railiance-apps
|
||||
status: active
|
||||
flavor: implementation
|
||||
owner: claude-code
|
||||
topic_slug: railiance
|
||||
created: "2026-10-08"
|
||||
updated: "2026-10-18"
|
||||
depends_on:
|
||||
- KEY-WP-0038
|
||||
related_repos:
|
||||
- prj-forgejo-org-refactor
|
||||
- key-cape
|
||||
- railiance-platform
|
||||
state_hub_workstream_id: "f6b1d6f6-0abb-5774-87b9-bf3cfb640a3b"
|
||||
---
|
||||
|
||||
# RAPPS-WP-0016 - Forgejo sign-in through NetKingdom, before the forge closes
|
||||
|
||||
## Why
|
||||
|
||||
`forgejo.coulomb.social` is closing: private by default, no anonymous access
|
||||
(prj-forgejo-org-refactor ORGREF-WP-0002, decision
|
||||
`decisions/forge-visibility-policy.md`). The founder's condition is that sign-in
|
||||
runs through NetKingdom first. railiance-apps owns the Forgejo Helm release
|
||||
(`docs/forgejo-on-railiance01.md`: S5 Helm release, ingress, operator Makefile),
|
||||
so the Forgejo side lands here. This plan is ORGREF-WP-0002-T05. The NetKingdom
|
||||
side is key-cape `KEY-WP-0038`.
|
||||
|
||||
## Boundaries
|
||||
|
||||
- **Founder guardrail:** tighten gradually; never lock anyone out; never risk
|
||||
assets; never reach a state that is hard to repair. Every step keeps the
|
||||
current sign-in path working until the new one is proven.
|
||||
- **No visibility change** in this plan. Repositories, packages and
|
||||
`REQUIRE_SIGNIN_VIEW` are ORGREF-WP-0002-T08.
|
||||
- **Configuration in git.** The authentication source is declared in
|
||||
`helm/forgejo-values.yaml` (`gitea.oauth`), with its secret drawn from an
|
||||
ExternalSecret over OpenBao. No click-ops, and no secret value in git.
|
||||
- Open registration is already disabled (`service.DISABLE_REGISTRATION: true`).
|
||||
This plan keeps it that way.
|
||||
|
||||
## Tasks
|
||||
|
||||
```task
|
||||
id: RAPPS-WP-0016-T01
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "98004ed0-83e6-5f6e-9b18-15b8b2aec2e7"
|
||||
```
|
||||
|
||||
### T01 — Make the local administrator a sealed break-glass
|
||||
|
||||
Before anything about sign-in changes: confirm the local administrator account
|
||||
works, keep its credential only in OpenBao, and document recovery (who, how,
|
||||
where it is logged) in `docs/forgejo-on-railiance01.md`. Verify one break-glass
|
||||
sign-in and record it without the credential.
|
||||
|
||||
Acceptance: a recorded break-glass sign-in, with the recovery path written down.
|
||||
This is the "never lock ourselves out" floor for every later step.
|
||||
|
||||
Done 2026-10-17: founder sealed `forgejo_admin` into OpenBao
|
||||
`platform/workloads/forgejo/break-glass-admin` (version 1) and verified a local
|
||||
sign-in (HTTP 200, site admin): `docs/evidence/2026-10-17-forgejo-breakglass-signin.json`.
|
||||
Recovery path: `docs/forgejo-on-railiance01.md` § Break-glass administrator.
|
||||
|
||||
```task
|
||||
id: RAPPS-WP-0016-T02
|
||||
status: wait
|
||||
depends_on: [RAPPS-WP-0016-T01, KEY-WP-0038-T02]
|
||||
blocking_reason: "Break-glass done (T01); needs the NetKingdom client registered with its secret in custody (KEY-WP-0038-T02)."
|
||||
priority: high
|
||||
state_hub_task_id: "13cd3aec-c87d-5d3f-a421-39d8ff131edd"
|
||||
```
|
||||
|
||||
### T02 — Add the NetKingdom authentication source
|
||||
|
||||
- an ExternalSecret delivering the `forgejo` client secret from OpenBao to a
|
||||
Secret in the `forgejo` namespace. Custody path is
|
||||
`platform/workloads/keycape/forgejo`, field `CLIENT_SECRET`, read by ESO through
|
||||
Kubernetes-auth role `external-secrets-keycape-forgejo-forgejo`, which carries
|
||||
only policy `workload-kv-read-keycape-forgejo-forgejo` (net-kingdom 074b3a0;
|
||||
replaces the earlier `platform/workloads/forgejo/netkingdom-oidc-client` proposal). The
|
||||
SA/SecretStore/ExternalSecret shape follows the NK-WP-0048
|
||||
`deliver-consumer-secret` receipt contract
|
||||
(`docs/evidence/nk48-t16-owner-review/owner-review-railiance-apps.json`)
|
||||
- `gitea.oauth`: name `netkingdom` (must match the redirect URI registered in
|
||||
key-cape), provider `openidConnect`, auto-discovery from
|
||||
`https://kc.coulomb.social/.well-known/openid-configuration`, scopes
|
||||
`openid profile email groups`, group-claim name `groups`
|
||||
- `oauth2_client` settings: no automatic account creation for unknown subjects;
|
||||
account linking to existing local accounts by username after a successful
|
||||
local sign-in (so the founder and agent accounts keep their history)
|
||||
- Helm upgrade with the previous revision noted for rollback
|
||||
|
||||
Local password sign-in stays enabled.
|
||||
|
||||
Acceptance: the "Sign in with netkingdom" option appears. Local sign-in still
|
||||
works. Rollback is one `helm rollback` to the noted revision.
|
||||
|
||||
```task
|
||||
id: RAPPS-WP-0016-T03
|
||||
status: wait
|
||||
depends_on: [RAPPS-WP-0016-T02]
|
||||
blocking_reason: "Linking and team mapping follow a working authentication source."
|
||||
priority: high
|
||||
state_hub_task_id: "81f072aa-c316-511e-a2cd-21dd1b1d0a00"
|
||||
```
|
||||
|
||||
### T03 — Link accounts and map groups to teams
|
||||
|
||||
- The founder links their account through NetKingdom (MFA), then signs in again
|
||||
through NetKingdom only and sees the same repositories, organisations and
|
||||
admin rights.
|
||||
- Map NetKingdom groups (names agreed in KEY-WP-0038-T01) to organisation teams:
|
||||
owners and readers at least. Create the read-only teams that
|
||||
ORGREF-WP-0002-T06 consumers will use.
|
||||
- Apply KEY-WP-0038-T03's decision on agents and services: NetKingdom sign-in, or
|
||||
scoped tokens bound to service identities.
|
||||
|
||||
Acceptance: founder and one agent work through NetKingdom; group-to-team mapping
|
||||
verified by adding and removing one test membership; break-glass still works.
|
||||
|
||||
```task
|
||||
id: RAPPS-WP-0016-T04
|
||||
status: wait
|
||||
depends_on: [RAPPS-WP-0016-T03]
|
||||
needs_human: true
|
||||
blocking_reason: "Restricting local password sign-in is a founder decision once NetKingdom sign-in is proven."
|
||||
priority: medium
|
||||
state_hub_task_id: "32c54737-c40f-5fde-9b91-163f8dcb0068"
|
||||
```
|
||||
|
||||
### T04 — Decide on local password sign-in
|
||||
|
||||
Once NetKingdom sign-in has been used for a while without problems, the founder
|
||||
decides whether local password sign-in is turned off for everyone except
|
||||
break-glass. This is not required to close the forge; it is the next tightening
|
||||
step, taken separately.
|
||||
|
||||
```task
|
||||
id: RAPPS-WP-0016-T05
|
||||
status: wait
|
||||
depends_on: [RAPPS-WP-0016-T02]
|
||||
blocking_reason: "Waits for net-kingdom's answer to the Apps 1.3 needs-change record (the-custodian docs/changes/netkingdom-target-2026-10-17/nk48-1.3-owner-review/owner-review-railiance-apps.json: RAPPS-1.3-C1..C3) and the re-frozen 1.3 candidate."
|
||||
priority: medium
|
||||
state_hub_task_id: "728786c9-f1f9-5983-a6a4-dea21faf67f5"
|
||||
```
|
||||
|
||||
### T05 — Apps owner seams for NK-WP-0048 consumer steps
|
||||
|
||||
Implement the real Apps capabilities behind the `deliver-consumer-secret` and
|
||||
`hand-over` adapters, as owner-run paths (option C): `owner_apply` /
|
||||
`owner_remove` emitting `netkingdom.consumer-secret-delivery.v1` receipts from the
|
||||
T02 objects; a consumer verifier that observes Forgejo sign-in and the T03
|
||||
positive/negative group probes; and a committed-evidence hand-over receipt store.
|
||||
See the owner-review record for the contract.
|
||||
|
||||
Acceptance: receipts produced from the live T02/T03 run validate against the
|
||||
adapters' checks with no value-bearing keys.
|
||||
|
||||
## Also in scope: stale node credential
|
||||
|
||||
The k3s `registries.yaml` on railiance01 still holds a login for the frozen Gitea
|
||||
host `92.205.130.254` (ORGREF-WP-0002-T02). Coordinate its removal with the node
|
||||
owner when ORGREF-WP-0002-T06 adds the forge registry login, in the same change.
|
||||
|
||||
|
||||
## T06 — Package the reviewed consumer source through the Apps build path
|
||||
|
||||
```task
|
||||
id: RAPPS-WP-0016-T06
|
||||
status: done
|
||||
priority: high
|
||||
```
|
||||
|
||||
Completed 2026-10-18, source build tooling only. The existing Apps Makefile now
|
||||
has explicit prepare, public-dependency acquisition, offline build, artifact
|
||||
verification and local OCI export targets for the pinned official Forgejo11.0.3
|
||||
source plus reviewed multi-value claim patch. Source/toolchains/locks/compiler
|
||||
inputs/base image are fixed. Third-party application source stays in a new /tmp
|
||||
workspace; Apps holds the release input lock, patch and build recipe.
|
||||
|
||||
The original build profile produced identical frontend assets, bindata sources
|
||||
and complete static executable in two workspaces, and identical local OCI
|
||||
archives in two no-cache exports. Independent review then found host process
|
||||
argv visibility through /proc (APPSBUILD-R1-F01). The revised recipe adds a
|
||||
private PID namespace; exact source and synthetic canary regression are separately
|
||||
reviewed. The original full builds are historical r1-profile evidence; no full
|
||||
r2 build is claimed. Original packet/review and failure history remain in
|
||||
Custodian apps-forgejo-release-build-r1 and apps-release-independent-review-r1;
|
||||
the correction is apps-forgejo-release-build-r2. This is coordinator source
|
||||
integration after independent technical review, not formal owner assent or image
|
||||
admission. Helm values, deployed image, local sign-in and visibility are unchanged.
|
||||
NK-WP-0048-T39 remains progress for the full release acceptance scope.
|
||||
|
||||
## T07 — Keep the client secret out of process arguments
|
||||
|
||||
```task
|
||||
id: RAPPS-WP-0016-T07
|
||||
status: progress
|
||||
priority: high
|
||||
```
|
||||
|
||||
Implement and independently review a real Forgejo add/update --secret-file path
|
||||
and the actual chart helper/mount adaptation. Preserve the existing CLIENT_SECRET
|
||||
key and custody route; use no agent-value argument or environment fallback. Test
|
||||
bounded stable nofollow file reads, exact existing minted-secret encoding,
|
||||
mutual exclusion/update preservation, fixed errors and actual Helm rendering.
|
||||
Private mount identity/reader set and new package/type revisions need explicit
|
||||
owner/runtime admission. The in-progress isolated candidate is Custodian
|
||||
forgejo-private-input-r1; source completion is distinct from T02 native delivery.
|
||||
|
||||
## T08 — Provide a transactional application-source inverse and durable recovery
|
||||
|
||||
```task
|
||||
id: RAPPS-WP-0016-T08
|
||||
status: progress
|
||||
priority: high
|
||||
```
|
||||
|
||||
Implement actual owner database primitives that record operation intent/outcome
|
||||
in the same durable database, compare complete raw persisted before/post/current
|
||||
source state privately, and serialize conflicting application writers at the DB
|
||||
boundary. Never emit stored credential/config bytes or delete/detach linked users
|
||||
or a preexisting/shared source. SQLite and PostgreSQL transaction semantics must
|
||||
be tested against the real app packages; unsupported backends refuse.
|
||||
|
||||
T05 and NK-WP-0048-T34 additionally require actual authenticated execution and
|
||||
fresh inverse sessions, admitted evidence/recovery and exclusion of every release
|
||||
writer, including Helm/runtime writers. The candidate DB primitive alone does
|
||||
not establish those facilities. Helm rollback/omission does not remove persisted
|
||||
OAuth sources: verify the exact app-state inverse before any image downgrade.
|
||||
If links prevent removal, retain the extended image and reconcile. The earlier
|
||||
T02 single-Helm-rollback statement is not sufficient recovery for this extension;
|
||||
its historical text is retained and corrected here.
|
||||
|
||||
## T09 — Enforce authenticated Access Engine decisions in the application path
|
||||
|
||||
```task
|
||||
id: RAPPS-WP-0016-T09
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
Use the producer-owned decision format/canonical bytes and independently admitted
|
||||
signer/policy/request pins. Forgejo must verify the caller's issuer/tenant and
|
||||
assurance facts, obtain and authenticate the exact Access Engine resource/action
|
||||
decision, and refuse missing, stale, wrong-pin, unavailable or malformed replies.
|
||||
Keep the original three-group any-of access set as policy input; its local
|
||||
compatibility gate is not a substitute PDP or an architecture exception. An
|
||||
issuer allowed/denied claim cannot manufacture authorization. Source integration
|
||||
needs real provider/callback/session wiring and meaningful producer-consumer
|
||||
positive/adverse tests before re-freezing the case and package. Existing break-
|
||||
glass/local account and linking behavior remain within the declared owner scope.
|
||||
Loading…
Add table
Add a link
Reference in a new issue