Compose Forgejo private-input and authenticated decision build candidate
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a14bfc-9643-7872-aa12-98326dcf25e7
This commit is contained in:
tegwick 2026-10-18 02:21:33 +02:00
parent c29408ae67
commit 3fb031a47f
5 changed files with 4756 additions and 12 deletions

View file

@ -1,7 +1,11 @@
# Forgejo release preparation (build only)
The Apps Makefile targets package the independently reviewed seven-path Forgejo
11.0.3 source extension. They never deploy, push, change default values or choose
The Apps Makefile targets package the digest-bound 37-path Forgejo 11.0.3
source candidate in `forgejo-security-extension.patch`. It combines the original
three-group any-of gate, private secret-file input, private source-operation DB
primitives and the producer-owned Access Engine client in the OIDC callback.
Coordinator source tests and complete release checks are recorded separately;
independent owner review and operational admission of this revision remain open. They never deploy, push, change default values or choose
an operational image. Third-party application source is expanded only into a new
`/tmp` workspace; this repository retains a release input lock and exact reviewed
patch, not a second source-code tree. Upstream source ownership and publication
@ -70,3 +74,40 @@ private secret-input boundary, type/case/descriptor re-freeze, current operation
inverse sessions, durable journal and application/Helm writer exclusion are
separate gates. Helm omission/rollback does not remove persisted OAuth source.
The existing case gate is compatibility code, not a single-PDP exception.
## KeyCape identity and callback admission
The callback independently verifies the ID token against owner-admitted public
keys, algorithms, issuer, audience and token type. Public trust is loaded from
`FORGEJO_ACCESS_ENGINE_ADMISSION_FILE`; only an absolute private file reference
is used for the PDP caller token. No admission file or operational keys are
supplied by this build. New fields `tenant_source_claim` and
`max_authentication_age` are mandatory. The KeyCape v0.3 profile uses
`assurance_claim: assurance` and `tenant_source_claim: tenant_source`. Maximum
identity age and maximum authentication age are separate positive durations
chosen by the owner, not implicit defaults.
The signed assurance object preserves `level`, `methods`, boolean `mfa`,
`source: key-cape` and integer `at`. Its authentication time must not follow
issuance or the current time, and must satisfy the admitted authentication-age
bound. Identity validity ends at the earliest token expiration, issued-at age
bound or authentication-age bound. Directory, registration and default tenant
provenance remain distinct in the request. Mutable UserInfo cannot replace
these authenticated facts. Current UserInfo subject and the Goth subject must
match the independently verified token; the three required group alternatives
remain policy input.
The parser also represents valid lower-assurance facts. Application policy
continues to decide authorization. The Check client and unchanged canonical
signature bytes are a generated source slice of Access Engine ca0cb757; Forgejo
adds no policy evaluator. Exact caller/policy/registry/signer/request/lifetime
pins, an authenticated HTTPS connection and a current ALLOW are required.
Synthetic callback fixtures test ALLOW, DENY and adverse cases, including an ID
token serialized by the actual pinned KeyCape handler. Those fixtures do not
prove an actual browser, factor, custody or native rollout.
The current integration covers this guarded OIDC callback. Ongoing application
HTTP/API/Git/SSH paths, current operation/inverse sessions, durable private
evidence and retention, PostgreSQL/native proof and exclusion of all release
writers remain open in RAPPS-WP-0016-T08/T09 and NK-WP-0048-T43. An old image
approval or source test result cannot admit this candidate.

File diff suppressed because it is too large Load diff

View file

@ -3,13 +3,13 @@
"forgejo_version": "11.0.3",
"source_archive_sha256": "1ddd8c926ca07d40436897971458ace7dcf1d3496a0813ab9e0d869edef2365c",
"source_commit": "b81aa4d0807cc1e2d6a2fbafd0b75c46cc0ae237",
"patch_sha256": "f2788b3f2bf84dbc0f94e232b6c9614a864b8123c09f9e44703d50d5e1b53257",
"patch_sha256": "15cb7f13b1b1d1095cc344176ca337f705333a436a70ae803fcfd3d7f802ccf4",
"go_archive_sha256": "3333f6ea53afa971e9078895eaa4ac7204a8c6b5c68c10e6bc9a33e8e391bdd8",
"go_version": "1.24.3",
"node_archive_sha256": "dafe2e8f82cb97de1bd10db9e2ec4c07bbf53389b0799b1e095a918951e78fd4",
"node_version": "22.15.0",
"source_date_epoch": 1752105237,
"release_version": "11.0.3+nk48.f2788b3f",
"release_version": "11.0.3+cust80.15cb7f13",
"tags": "bindata timetzdata sqlite sqlite_unlock_notify",
"runtime_base": "code.forgejo.org/forgejo/forgejo@sha256:41649dff5311664097d29b4d80620403f0b27e7c0eee0b8af79b132a37f3807b",
"runtime_index_digest": "sha256:691657c7e64af7730a2e885e6d022cf16ae60724931c5392bd61838afadcaeba",
@ -17,7 +17,59 @@
"reviewed_outputs": [
{
"path": "cmd/admin_auth_oauth.go",
"sha256": "1dd03f0bd23889a340a10fcc18d2e3a49270b79056aafd1b3baf01b18559b37f"
"sha256": "d718d817c46f6393488a9c5a894b7535640cd0ec1a1ae3f72f8411a2bbec3b38"
},
{
"path": "cmd/admin_auth_oauth_secret_linux.go",
"sha256": "6741961f1df67c1afbf34c796e549425f0e04a0d0678c6eedb05f66d4754c64b"
},
{
"path": "cmd/admin_auth_oauth_secret_linux_test.go",
"sha256": "b28c2369dfab9bf2ca48e707e01b4394a36c8be5490cfe5bb658017bb626c4b2"
},
{
"path": "cmd/admin_auth_oauth_secret_other.go",
"sha256": "54056c989a4757e73db0252130e7c16bf16f5ec8eaaca2468f019ba2ef5c532d"
},
{
"path": "go.mod",
"sha256": "130138c4c3ecc29fa0d7f1e2eef0589ddf3b06071f3cc0448aa7b2326847653a"
},
{
"path": "models/auth/source_operation.go",
"sha256": "ef1b07ef6cf454015d00cde8588835f5118d829da91eb0303d37184859345a31"
},
{
"path": "models/auth/source_operation_internal_test.go",
"sha256": "af0f424d3a1fd2b29793b64baa1fa07284fee7ea0b7721c503db4efac0d871cb"
},
{
"path": "models/auth/source_operation_process_test.go",
"sha256": "40d33b11a01cb659f0bf6f8b545c4d79910e8c082a789060bcbc9cadeee965bd"
},
{
"path": "models/auth/source_operation_test.go",
"sha256": "77d311bca42f48faf3fbdc15c53582e3d8a6d9108a72ed7bb6172e5b88951428"
},
{
"path": "models/db/context.go",
"sha256": "d4c4acfcb8987071aecf5cd957b3821c8d2619a2696398d37c2970f2527686f7"
},
{
"path": "models/db/engine.go",
"sha256": "43683804d0c5bc6ead1dba0344c69dd196825cf3d5eb502af8d932a7b8207b96"
},
{
"path": "models/db/sensitive_sql.go",
"sha256": "06a298d0d6e628e6920384d4ddeef449e40c090841ebaa3f6d175725a45ae584"
},
{
"path": "models/db/sensitive_sql_logging_test.go",
"sha256": "d924b35d30686473caf29601cf51cc363ba68158cb4ef0981c9e2fc7b03c04b7"
},
{
"path": "models/db/sensitive_sql_test.go",
"sha256": "de6353c955047c3311747e4777b9f9b2195e9efb19160b971dd758dfc94cf31b"
},
{
"path": "routers/web/admin/auths.go",
@ -25,7 +77,31 @@
},
{
"path": "routers/web/auth/oauth.go",
"sha256": "081bcb94023d6e27289196bbe518bebba0a8a6082ea1a32d2794c5562075907b"
"sha256": "58bff778e0dc17a521706289bf45c3e0d76a759a0874f76c379b3d1ddb419b17"
},
{
"path": "services/auth/source/oauth2/access_engine.go",
"sha256": "d5f07f9491ac2212410e1fa8c0248d68ba3a723e7ca99e363627c5292d187aa8"
},
{
"path": "services/auth/source/oauth2/access_engine_assurance.go",
"sha256": "42de751b1e9a243301d566260954813b770558ecb449639acaeab307fe788642"
},
{
"path": "services/auth/source/oauth2/access_engine_assurance_test.go",
"sha256": "44e7459f6c1106a264093c19d61d01a8365f6ad22682906552d832ba39d61dd3"
},
{
"path": "services/auth/source/oauth2/access_engine_azp_test.go",
"sha256": "5f94f43ade9a79b6b7ef529c80115a8c32acfece425dc8ed3f24e6ad839fc0ce"
},
{
"path": "services/auth/source/oauth2/access_engine_callback_test.go",
"sha256": "5cea36b630c895a9473dc876b7128526ddef65d9395b2fddc56343e162452472"
},
{
"path": "services/auth/source/oauth2/access_engine_test.go",
"sha256": "99edd6cfe3e834d73e0447a7915f52cc4ab7b82644669c5ae61963f850b447e8"
},
{
"path": "services/auth/source/oauth2/providers_openid.go",
@ -42,10 +118,54 @@
{
"path": "services/auth/source/oauth2/source.go",
"sha256": "44e99883c2ec479427b3f72c73353fe33936eed2e5c962b2fa40803576aa5642"
},
{
"path": "services/auth/source/oauth2/source_callout.go",
"sha256": "6abba69df97afc62467f0328eaa5a6383cfb4900202a081dec4b84a21b37349c"
},
{
"path": "third_party/access-engine-pep/LICENSE",
"sha256": "ff413f361a3b3bf44cf50f110fbcc4837064d57eefbcef89df2b43997c6262b6"
},
{
"path": "third_party/access-engine-pep/go.mod",
"sha256": "fea700810e47c1ba5638b86a168f8531c083a6e1222ca80bd2a8947b2ea6f2c3"
},
{
"path": "third_party/access-engine-pep/internal/sign/sign.go",
"sha256": "0df9515922e90775ebbfac798361dcafb20da8a4213796b44e246b8a92046cde"
},
{
"path": "third_party/access-engine-pep/pkg/api/canonical.go",
"sha256": "a122a2e8cd524333b13c5939c7a3685e41efbe47497a64e0c7297c92b7f10d19"
},
{
"path": "third_party/access-engine-pep/pkg/api/caring.go",
"sha256": "1907156f0f889e7b9e9c14970cf7a86a20d00478a496efaf92c7231f27fec5e3"
},
{
"path": "third_party/access-engine-pep/pkg/api/resource_manifest.go",
"sha256": "f0fa4080287d389ed48c2b1d6af96cc62e57ef72c902333f677f964420be133f"
},
{
"path": "third_party/access-engine-pep/pkg/decisionpep/client.go",
"sha256": "0d57f6ddaca5c3f81ce426c0e8b14ba14ea5962096d3be5909aa456eef19eeba"
},
{
"path": "third_party/access-engine-pep/pkg/decisionpep/client_test.go",
"sha256": "1a6be3485f580f95a1f1406fb76e525f2c4bf02fe04a424cfe0095bb728e3f62"
},
{
"path": "third_party/access-engine-pep/producer-source.json",
"sha256": "c1d83e3d79f9860ffaa61ec19a6b3415e914d3058b11b07cdd05a7d1182cdceb"
},
{
"path": "third_party/access-engine-pep/testsupport/signfixture/sign.go",
"sha256": "fe4aa86f444dc20145aefbaca35b24f046264b2c5c8b4e3b057a4496b77a4d29"
}
],
"lockfiles": {
"go.mod": "652162a4a95c6d1c349d2a8c0b514def5abd837f001137b77b7b3f4a0f162d00",
"go.mod": "130138c4c3ecc29fa0d7f1e2eef0589ddf3b06071f3cc0448aa7b2326847653a",
"go.sum": "19c305c7e68de9d3f1bc0dda2de09c5d38597f1ee7fa411c7b36b92467ae1eaf",
"package.json": "ab5c54ec7077501b50acf3ab5f1fff4f63a51abe99e720b8ecdc6cc6c78f39fc",
"package-lock.json": "fdd5c2f891311be7c01b1907b418c243ca1f0f951fd4b4ee5b5e931c43493657"
@ -59,5 +179,8 @@
"/usr/lib/x86_64-linux-gnu/libc.a": "a40c7eae7581f977b65eddb81cbc799213a695749e039d966db55bdee4ac9621",
"/usr/lib/x86_64-linux-gnu/libm.a": "420cd3c406f6f8c12deb3d1291146e9c091ee015a7c39eaf2237f01e80d6f0ae"
},
"runtime_base_config_sha256": "bc5a3df111729582faadebd01d126ba769e2b65d0c62f306f6bc79f4e562452b"
"runtime_base_config_sha256": "bc5a3df111729582faadebd01d126ba769e2b65d0c62f306f6bc79f4e562452b",
"patch_file": "forgejo-security-extension.patch",
"candidate_review_status": "coordinator tested; independent owner review pending",
"producer_source_commit": "ca0cb75729a63c9288b7333382d0fa3eb1e8c9a3"
}

View file

@ -73,7 +73,7 @@ def prepare(a,work):
check(getattr(a,n),LOCK[key])
if not a.module_cache:raise ValueError('explicit public module cache required')
cache=Path(a.module_cache).resolve();assert cache.is_dir()
check(INPUTS/'required-claim-values.patch',LOCK['patch_sha256'])
check(INPUTS/LOCK['patch_file'],LOCK['patch_sha256'])
for n,h in LOCK['host_tools'].items():check(n,h)
work.mkdir(parents=True);(work/'home').mkdir()
with tarfile.open(a.source_archive) as t:
@ -85,8 +85,8 @@ def prepare(a,work):
for n in ['empty.npmrc','empty-global.npmrc']:(work/n).write_text('')
if a.go_cache_seed:shutil.copytree(Path(a.go_cache_seed).resolve(),work/'gocache')
if a.npm_cache_seed:shutil.copytree(Path(a.npm_cache_seed).resolve(),work/'npm-cache')
subprocess.run(['/usr/bin/git','apply','--check',str(INPUTS/'required-claim-values.patch')],cwd=work/'source',check=True,env={'PATH':'/usr/bin:/bin','HOME':str(work/'home'),'GIT_CONFIG_NOSYSTEM':'1','GIT_CONFIG_GLOBAL':'/dev/null'})
subprocess.run(['/usr/bin/git','apply',str(INPUTS/'required-claim-values.patch')],cwd=work/'source',check=True,env={'PATH':'/usr/bin:/bin','HOME':str(work/'home'),'GIT_CONFIG_NOSYSTEM':'1','GIT_CONFIG_GLOBAL':'/dev/null'})
subprocess.run(['/usr/bin/git','apply','--check',str(INPUTS/LOCK['patch_file'])],cwd=work/'source',check=True,env={'PATH':'/usr/bin:/bin','HOME':str(work/'home'),'GIT_CONFIG_NOSYSTEM':'1','GIT_CONFIG_GLOBAL':'/dev/null'})
subprocess.run(['/usr/bin/git','apply',str(INPUTS/LOCK['patch_file'])],cwd=work/'source',check=True,env={'PATH':'/usr/bin:/bin','HOME':str(work/'home'),'GIT_CONFIG_NOSYSTEM':'1','GIT_CONFIG_GLOBAL':'/dev/null'})
save(work/'prepared.json',{'module_cache':str(cache),'lock_sha256':digest(INPUTS/'inputs.lock.json'),'public_archives_verified':True})
checked_inputs(work)
packages=json.loads((work/'source/package-lock.json').read_text())['packages']
@ -136,6 +136,7 @@ def verify(work):
run(work,'binary-version',bare+['--version'],outer)
run(work,'new-cli-help',bare+['admin','auth','add-oauth','--help'],outer)
assert '--required-claim-values' in (work/'new-cli-help.log').read_text()
assert '--secret-file' in (work/'new-cli-help.log').read_text()
run(work,'embedded-extract',bare+['embedded','extract','--include-vendored','--destination','/results','**'],outer)
records={}
for folder in ['public','options','templates']:

View file

@ -246,7 +246,7 @@ its historical text is retained and corrected here.
```task
id: RAPPS-WP-0016-T09
status: todo
status: progress
priority: high
state_hub_task_id: "d3804638-c73d-5b9f-a456-4262f62f9e6b"
```
@ -261,3 +261,23 @@ 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.
2026-10-18 source continuation for T07/T08/T09: the digest-bound build
candidate now composes all 37 paths, including private secret-file input, actual
source-state transactions/private SQL hooks, the producer-owned Access Engine
Check client from ca0cb757 and guarded OIDC callback enforcement. The parser uses
the actual KeyCape typed assurance/authentication-time/provenance contract; its
actual issuer fixture/callback suite passes 71 test/subtest results, and selected
composed packages pass 93 with no skips. The previous incompatible-string-claim
rejection is retained. All patch postimages independently replay from the pinned
official archive. Complete release build/verification is tracked in Custodian
forgejo-keycape-claims-r1; earlier release outputs do not prove this revision.
This is coordinator source integration of a tested build candidate; independent
owner review and formal operational admission remain open. T07's chart/private
mount admission, T08's fresh authenticated operation/inverse and release-wide
writer exclusion, T09's ongoing HTTP/API/Git/SSH paths, private evidence/retention,
PostgreSQL/native proof and actual issuer/factor/custody acceptance remain open.
No trust, deployed image, Helm values, source DB, user/link state or local sign-in
is changed by this build-source update. The preserved legacy patch is historical;
the input lock now explicitly selects forgejo-security-extension.patch.