Record the Gate 6 local security evidence

bb74a35618ba · Christopher David · · parent 04b2faf47080

Record the Gate 6 local security evidence

Deploy story

What this commit did to the running system — joined from the forge receipt chain, the part a commit page elsewhere cannot show.

Not deployed through the forge lane

No push, promotion, build, or deploy receipt references this commit (receipts are scanned over a bounded recent window). Changes shipped by full node replacement carry their proof in the release gate receipt instead.

Changed files

  • modified docs/2026-08-20-integration-hardening-and-staging-readiness-recommendations.md
  • added docs/evidence/gate-6/04b2faf47080aa7b5bce43b4319fa0276eb3da05/README.md
  • added docs/evidence/gate-6/04b2faf47080aa7b5bce43b4319fa0276eb3da05/baseline-receipt.json
  • added docs/evidence/gate-6/04b2faf47080aa7b5bce43b4319fa0276eb3da05/gate-6-local-receipt.json

Diff

4 files changed, +130 -3

docs/2026-08-20-integration-hardening-and-staging-readiness-recommendations.md modified +55 -3

@@ -2,7 +2,7 @@

2 2
3 3
Date: 2026-08-20
4 4
5
Status: In progress; Gates 0–3 complete, amended with measured findings
5
Status: In progress; Gates 0–5 complete, Gate 6 application controls locally verified
6 6
7 7
## Outcome
8 8

@@ -591,6 +591,56 @@ inventory test.

591 591
token behavior matches its documentation, and staging logs contain no secret or
592 592
private-content fields.
593 593
594
### Gate 6 implementation status
595
596
Application controls were completed and locally verified on 2026-08-20:
597
598
- Chose the identity-and-GitHub-tools model. The consent UI now says that the
599
  retained, encrypted `repo` grant carries GitHub-side read/write authority
600
  even though OpenAgents exposes it only to bounded repository-read tools.
601
  Public profile identity needs no scope, so the redundant `read:user` request
602
  was removed. Missing, reduced, or broadened granted scopes fail closed.
603
- Added a versioned AES-256-GCM envelope with an environment-specific active
604
  key ID, a bounded same-environment prior-key map, transactional rewrap, and
605
  an executable release rotation command. Explicit disconnect revokes the
606
  GitHub grant before a compare-and-clear operation, so provider failure or a
607
  concurrent reconnection cannot silently discard the wrong grant.
608
- Added non-secret GitHub connection and first-party API credential metadata to
609
  account export. Product-data deletion and the UI now state that credentials
610
  remain until their independent disconnect or revoke action.
611
- Added an executable inventory for every HTTP route and endpoint socket across
612
  public-read, authenticated-browser, authenticated-API, operator, machine,
613
  internal-service, and Git-transport authority classes. New or misclassified
614
  mutations fail the test gate.
615
- Split public `/api/v3` reads from writes. Writes now require an expiring,
616
  revocable, digest-only `oa_pat_` bearer with exact `forge:write` scope;
617
  missing, malformed, unknown, expired, revoked, and wrong-scope credentials
618
  receive the same refusal. Browser token management remains session-bound and
619
  CSRF-protected.
620
- Made machine credentials expire, disconnect active channels at expiry, and
621
  moved pairing claim to a row-locked one-time transition with a concurrent
622
  winner test. Existing inference grants remain scoped, expiring, budgeted,
623
  revocable, and generation-fenced.
624
- Added a staging secret and runtime-identity inventory, environment-fenced
625
  vault keys, credential-free builder and mirror URLs, bounded operational
626
  error codes, global sensitive-parameter filtering, OAuth callback log
627
  suppression, build-output redaction, and a log scanner that reports finding
628
  classes and line numbers without echoing private values.
629
- Rehearsed all three Gate 6 migrations down and back up on disposable
630
  PostgreSQL. Exact implementation commit
631
  `04b2faf47080aa7b5bce43b4319fa0276eb3da05` then passed the owned baseline in
632
  80 seconds with 1,267 default Elixir tests, all 9 distributed tests, 17
633
  browser tests, 83.29% merged coverage, the packaged production release
634
  startup, and zero automatic retries. See the
635
  [Gate 6 local evidence](evidence/gate-6/04b2faf47080aa7b5bce43b4319fa0276eb3da05/README.md).
636
637
Gate 6 is not operationally closed. No staging deployment occurred. Before
638
Gate 15 admission, rotate every pre-gate staging credential, revoke and
639
reauthorize any legacy `read:user,repo` grant, configure the load balancer to
640
omit OAuth callback query strings, export logs from every named source for the
641
complete test window, and pass the private-log scanner plus manual plaintext
642
review. That exact-SHA staging record is the remaining Gate 6 exit criterion.
643
594 644
## Gate 7: Add real repository and tenant scoping
595 645
596 646
The Issues and Projects routes carry `owner` and `repo`, but several contexts

@@ -1186,8 +1236,10 @@ each handoff.

1186 1236
      two-tier icon policy.
1187 1237
- [x] The dark-only palette has no nonfunctional theme control.
1188 1238
- [x] Runtime configuration is typed, redacted, and staging-specific.
1189
- [ ] Every route has an explicit authority class.
1190
- [ ] GitHub token behavior matches code, UI disclosure, and data rights.
1239
- [x] Every route has an explicit authority class.
1240
- [x] GitHub token behavior matches code, UI disclosure, and data rights.
1241
- [ ] Gate 6 staging credentials are rotated and the complete staging log
1242
      window passes automated and manual private-content review.
1191 1243
- [ ] Issues and Projects are scoped by repository in code and PostgreSQL.
1192 1244
- [ ] Every asynchronous recovery path has direct tests.
1193 1245
- [ ] Browser-side voice, recording, and hook tests run in the owned gate.
docs/evidence/gate-6/04b2faf47080aa7b5bce43b4319fa0276eb3da05/README.md added +29

@@ -0,0 +1,29 @@

1
# Gate 6 local evidence
2
3
Date: 2026-08-20
4
5
Candidate: `04b2faf47080aa7b5bce43b4319fa0276eb3da05`
6
7
Status: Local application controls passed; staging operational proof pending
8
9
The exact committed candidate passed the owned baseline without retries:
10
11
- `mix precommit`: passed
12
- default Elixir tests: 1,267 passed; 9 cluster-tagged tests excluded
13
- browser JavaScript tests: 17 passed
14
- distributed Elixir tests: 9 passed
15
- merged line coverage: 83.29%, above the enforced 83% floor
16
- packaged production release build, readiness, migrations, startup, bounded
17
  health response, and graceful termination: passed against disposable
18
  PostgreSQL
19
- Gate 6 migration rollback and forward rehearsal: passed
20
21
The retained [baseline receipt](baseline-receipt.json) is content-free and tied
22
to the implementation SHA. The [Gate 6 receipt](gate-6-local-receipt.json)
23
records which controls this local evidence covers and which staging operations
24
remain blocking.
25
26
No staging or production deployment occurred. This evidence does not claim the
27
required staging credential rotation, load-balancer query suppression, or
28
full-window staging log scan. Those checks remain mandatory before Gate 6 can
29
close and before the Gate 15 candidate can be admitted.
docs/evidence/gate-6/04b2faf47080aa7b5bce43b4319fa0276eb3da05/baseline-receipt.json added +21

@@ -0,0 +1,21 @@

1
{
2
  "schema": "openagents.baseline-gate.v1",
3
  "git_sha": "04b2faf47080aa7b5bce43b4319fa0276eb3da05",
4
  "status": "passed",
5
  "started_at": "2026-08-20T08:15:55Z",
6
  "completed_at": "2026-08-20T08:17:15Z",
7
  "total_duration_seconds": 80,
8
  "automatic_retries": 0,
9
  "stages": {
10
    "precommit": {"status": "passed", "duration_seconds": 20},
11
    "coverage": {"status": "passed", "duration_seconds": 51},
12
    "release_smoke": {"status": "passed", "duration_seconds": 9}
13
  },
14
  "tests": {
15
    "javascript": 17,
16
    "default": 1267,
17
    "cluster": 9,
18
    "excluded_from_default": 9
19
  },
20
  "coverage_percent": 83.29
21
}
docs/evidence/gate-6/04b2faf47080aa7b5bce43b4319fa0276eb3da05/gate-6-local-receipt.json added +25

@@ -0,0 +1,25 @@

1
{
2
  "schema": "openagents.gate-6-local-evidence.v1",
3
  "git_sha": "04b2faf47080aa7b5bce43b4319fa0276eb3da05",
4
  "status": "local_controls_passed_staging_proof_pending",
5
  "migration_rehearsal": {
6
    "github_token_lifecycle": "down_up_passed",
7
    "api_tokens": "down_up_passed",
8
    "machine_token_expiry": "down_up_passed"
9
  },
10
  "controls": {
11
    "github_consent_scope_storage_rotation_disconnect": "passed",
12
    "route_authority_inventory": "passed",
13
    "browser_csrf_and_api_bearer_split": "passed",
14
    "machine_expiry_and_pairing_replay": "passed",
15
    "bounded_log_and_receipt_handling": "passed"
16
  },
17
  "staging": {
18
    "deployment_performed": false,
19
    "credentials_rotated": false,
20
    "oauth_query_suppression_verified": false,
21
    "complete_log_window_scanned": false,
22
    "manual_plaintext_reviewed": false
23
  },
24
  "production_action_performed": false
25
}

This page updates live while a promote is in flight · changelog