diff --git a/docs/changes/netkingdom-target-2026-10-17/apps-forgejo-release-build-r1/README.md b/docs/changes/netkingdom-target-2026-10-17/apps-forgejo-release-build-r1/README.md new file mode 100644 index 0000000..5ca4600 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-17/apps-forgejo-release-build-r1/README.md @@ -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. diff --git a/docs/changes/netkingdom-target-2026-10-17/apps-forgejo-release-build-r1/evidence/binary-reproduction.json b/docs/changes/netkingdom-target-2026-10-17/apps-forgejo-release-build-r1/evidence/binary-reproduction.json new file mode 100644 index 0000000..69952b6 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-17/apps-forgejo-release-build-r1/evidence/binary-reproduction.json @@ -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 +} diff --git a/docs/changes/netkingdom-target-2026-10-17/apps-forgejo-release-build-r1/evidence/container-reproduction.json b/docs/changes/netkingdom-target-2026-10-17/apps-forgejo-release-build-r1/evidence/container-reproduction.json new file mode 100644 index 0000000..993d38f --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-17/apps-forgejo-release-build-r1/evidence/container-reproduction.json @@ -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 +} diff --git a/docs/changes/netkingdom-target-2026-10-17/apps-forgejo-release-build-r1/source-inventory.json b/docs/changes/netkingdom-target-2026-10-17/apps-forgejo-release-build-r1/source-inventory.json new file mode 100644 index 0000000..67c71d5 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-17/apps-forgejo-release-build-r1/source-inventory.json @@ -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 +} diff --git a/docs/changes/netkingdom-target-2026-10-17/apps-forgejo-release-build-r1/validation.json b/docs/changes/netkingdom-target-2026-10-17/apps-forgejo-release-build-r1/validation.json new file mode 100644 index 0000000..7acf19e --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-17/apps-forgejo-release-build-r1/validation.json @@ -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 +} diff --git a/docs/changes/netkingdom-target-2026-10-17/apps-forgejo-release-build-r2/source-refinement.json b/docs/changes/netkingdom-target-2026-10-17/apps-forgejo-release-build-r2/source-refinement.json new file mode 100644 index 0000000..82ce24d --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-17/apps-forgejo-release-build-r2/source-refinement.json @@ -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." + } +} diff --git a/docs/changes/netkingdom-target-2026-10-17/apps-release-independent-review-r1/proc-boundary-result.json b/docs/changes/netkingdom-target-2026-10-17/apps-release-independent-review-r1/proc-boundary-result.json new file mode 100644 index 0000000..6903327 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-17/apps-release-independent-review-r1/proc-boundary-result.json @@ -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 \"\", line 1, in \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 +} diff --git a/docs/changes/netkingdom-target-2026-10-17/apps-release-independent-review-r1/proc-boundary-test.py b/docs/changes/netkingdom-target-2026-10-17/apps-release-independent-review-r1/proc-boundary-test.py new file mode 100644 index 0000000..f9aeb65 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-17/apps-release-independent-review-r1/proc-boundary-test.py @@ -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)) diff --git a/docs/changes/netkingdom-target-2026-10-17/apps-release-independent-review-r1/review.json b/docs/changes/netkingdom-target-2026-10-17/apps-release-independent-review-r1/review.json new file mode 100644 index 0000000..8af6839 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-17/apps-release-independent-review-r1/review.json @@ -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 + } +} diff --git a/docs/changes/netkingdom-target-2026-10-17/apps-release-independent-review-r2/results.json b/docs/changes/netkingdom-target-2026-10-17/apps-release-independent-review-r2/results.json new file mode 100644 index 0000000..0da8ab3 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-17/apps-release-independent-review-r2/results.json @@ -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 +} diff --git a/docs/changes/netkingdom-target-2026-10-17/apps-release-independent-review-r2/review.json b/docs/changes/netkingdom-target-2026-10-17/apps-release-independent-review-r2/review.json new file mode 100644 index 0000000..827e10d --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-17/apps-release-independent-review-r2/review.json @@ -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 + } +} diff --git a/docs/changes/netkingdom-target-2026-10-17/apps-release-source-integration-r1/apply_source.py b/docs/changes/netkingdom-target-2026-10-17/apps-release-source-integration-r1/apply_source.py new file mode 100644 index 0000000..588adb9 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-17/apps-release-source-integration-r1/apply_source.py @@ -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})) diff --git a/docs/changes/netkingdom-target-2026-10-17/apps-release-source-integration-r1/identifier-assignment.json b/docs/changes/netkingdom-target-2026-10-17/apps-release-source-integration-r1/identifier-assignment.json new file mode 100644 index 0000000..5763f54 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-17/apps-release-source-integration-r1/identifier-assignment.json @@ -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" + ] +} diff --git a/docs/changes/netkingdom-target-2026-10-17/apps-release-source-integration-r1/source-application.json b/docs/changes/netkingdom-target-2026-10-17/apps-release-source-integration-r1/source-application.json new file mode 100644 index 0000000..530c609 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-17/apps-release-source-integration-r1/source-application.json @@ -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 +} diff --git a/docs/changes/netkingdom-target-2026-10-17/apps-release-source-integration-r1/verified-task-bindings.json b/docs/changes/netkingdom-target-2026-10-17/apps-release-source-integration-r1/verified-task-bindings.json new file mode 100644 index 0000000..c7de4ac --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-17/apps-release-source-integration-r1/verified-task-bindings.json @@ -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 +} diff --git a/docs/changes/netkingdom-target-2026-10-17/apps-release-source-integration-r1/workplan.md b/docs/changes/netkingdom-target-2026-10-17/apps-release-source-integration-r1/workplan.md new file mode 100644 index 0000000..6298c87 --- /dev/null +++ b/docs/changes/netkingdom-target-2026-10-17/apps-release-source-integration-r1/workplan.md @@ -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. diff --git a/docs/netkingdom-target-implementation.md b/docs/netkingdom-target-implementation.md index c972f5c..028fe8d 100644 --- a/docs/netkingdom-target-implementation.md +++ b/docs/netkingdom-target-implementation.md @@ -1231,3 +1231,45 @@ public digest/Git metadata where the unchanged scanner rejected raw public identifiers. Exact frozen original bytes are verified and reconstructable using `owner-followthrough-publication-r1/reconstruct_public_metadata.py`; its receipt records the derivation. Code/chart bytes, scanner rules and authority are unchanged. +## 18 October: application build source and remaining operation boundaries + +Apps source `c29408ae` adds the pinned Forgejo release input lock, reviewed patch, +offline frontend/static-binary build, embedded-asset verification and local OCI +export through its existing Makefile. The normal owner publication and primary +projection are verified in +`apps-release-source-integration-r1/verified-task-bindings.json`: all nine +RAPPS-WP-0016 task bindings match source. T06 records build tooling only; T07/T08 +track private input and the transactional inverse, while T09 owns actual Access +Engine application enforcement. Existing five task blocks and the staged brief +are preserved. Neither deployed image nor Helm values changed. + +The original build profile produced identical complete binaries and OCI archives. +Independent review reproduced all 2,234 embedded assets and checked both source +workspaces and image contents, but found unrelated process arguments visible +through `/proc`. Its changes-required decision is retained. Exact r2 adds a +private PID namespace; a synthetic canary demonstrates r1 exposure and r2 refusal. +The accepted source correction is now integrated. Historical full-build evidence +belongs to r1; no full r2 rebuild or native deployment is claimed. See +`apps-release-independent-review-r1/`, `apps-forgejo-release-build-r2/` and +`apps-release-independent-review-r2/` under the dated changes directory. + +Three further assignments use the founder-requested GPT-6.1-Sol medium model. +Private-input work changes the actual Forgejo CLI and chart helper together; +a file-path flag alone would leave the chart's secret argument exposed. The +transaction work uses actual database comparisons, durable private state and +SQLite competing-writer/crash tests. It also addresses SQL error/slow/trace +argument leakage through one shared redaction implementation. Those private +journals introduce additional credential copies inside the owner DB; custody, +capacity, retention and recovery remain explicit obligations. No public receipt +contains their configuration or credential values. + +The Access Engine assignment implements a producer-owned reusable verifier and +actual consumer integration. Decoded identity claims are insufficient: issuer +JWT signature/type/algorithm/audience/lifetime validation and a trusted identity +snapshot must precede UserInfo/PDP use. A login callback alone cannot establish +ongoing HTTP/API/Git/SSH authorization coverage. Producer numeric compatibility, +current operation/inverse identities and independently admitted signer/policy/ +caller/runtime inputs remain within that assignment's acceptance scope. These +source activities do not close T34/T37/T39, T06 native acceptance, or any of the +sixteen architecture gates. +