Skip to content

Cockpit C1 — Repair Job Authority Envelope & Merge Barrier - #14

Draft
LogicDuke wants to merge 8 commits into
mainfrom
cockpit/c1-job-authority
Draft

Cockpit C1 — Repair Job Authority Envelope & Merge Barrier#14
LogicDuke wants to merge 8 commits into
mainfrom
cockpit/c1-job-authority

Conversation

@LogicDuke

Copy link
Copy Markdown
Owner

Purpose

C1 establishes the pure TypeScript repair-job authority boundary for the future AgentBridge Cockpit.

It models:

  • bounded repair-job authorization;
  • exact operation operands;
  • one-execution permit records;
  • protected-parent / repair-branch separation;
  • independent-validator separation;
  • ordinary-job hard denial of merge and auto-merge;
  • the structural shape of future operator merge authorization.

C1 performs no filesystem, Git, GitHub, subprocess, network, persistence, workflow-state, or merge execution.

The historical V1 read-only boundary remains preserved. Future write authority is explicitly job-scoped and is not granted by this PR itself.

Status

DRAFT — BLOCKED BY CURRENT INDEPENDENT-AUDIT FINDINGS.

This PR is the protected C1 parent integration branch.

Known CURRENT findings at this baseline:

C1-A01 — P2

resolveJobOperation uses uncaptured Map.prototype.get; hostile prototype mutation can corrupt operation resolution and potentially turn forbidden/unknown operations into an allowed modeled operation.

File: src/domain/job-operation.ts

C1-A02 — P2

OperatorMergeAuthorization / operatorMergeAuthorizes documentation overstates what is proven. Current C1 performs structural binding checks but does not authenticate operator identity/origin and does not enforce one-time consumption.

Files: src/domain/execution-permit.ts, docs/architecture/C1-repair-job-authority.md

C1-A03 — P3

readList uses ordinary indexed reads; a sparse authorization list plus a prototype-planted numeric property can fabricate authorization scope.

File: src/domain/repair-job.ts

These findings MUST NOT be repaired directly on this protected parent branch.

Each finding will enter an isolated repair branch/worktree and stacked validation PR targeting this branch.

Quarantine rule

Finding
→ verify against CURRENT C1 HEAD
→ isolated repair branch/worktree
→ bounded repair
→ stacked validation PR
→ independent review
→ complete validation
→ operator merge decision
→ re-audit parent HEAD

No implementing agent is its own sole validator.

Merge boundary

MERGE IS OPERATOR-ONLY.

No AI agent is authorized to merge this PR or any stacked repair PR.

No auto-merge.

Baseline verification

Re-run against this exact baseline commit immediately before it was created:

Check Command Result
Typecheck npm run typecheck PASS (exit 0)
Lint npm run lint PASS (exit 0, eslint strictTypeChecked)
Tests npm test PASS — 839 passed, 15 test files, 0 failed
Build npm run build PASS (exit 0)
Audit npm audit 0 vulnerabilities
Whitespace git diff --check / git diff --cached --check clean (exit 0)

Passing tests are evidence, not proof; the independent audit findings above remain blocking.

Baseline scope

Exactly ten files, 4614 insertions, 0 deletions. No dependency, package.json, package-lock.json, CI, tsconfig, eslint, or vitest change. No PR #9 or PR #10 content.

  • src/domain/index.ts (additive re-exports only)
  • src/domain/repair-job.ts
  • src/domain/job-operation.ts
  • src/domain/execution-permit.ts
  • src/domain/job-authorization.ts
  • tests/domain/repair-job-fixtures.ts
  • tests/domain/job-authorization.test.ts
  • tests/domain/job-authorization-invariants.test.ts
  • tests/domain/execution-permit.test.ts
  • docs/architecture/C1-repair-job-authority.md

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e4910f4c-3865-40d3-b774-0e9b83aff66e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

C1-A01 (P2). `resolveJobOperation` resolved operation names through
`OPERATION_LOOKUP.get(value)`. `Map.prototype.get` is looked up at call
time, so a hostile replacement installed after module initialization could
map any requested name onto a repair-authorizable one.

Reproduced from the parent baseline: with `Map.prototype.get` returning
`source.edit`, a valid repair-job envelope resolved `merge` to `source.edit`
and produced ALLOW_ONCE / WITHIN_JOB_ENVELOPE with an execution permit
issued. The same corruption applied to `auto_merge.enable` and to unmodeled
names such as `shell.exec`.

Remove the Map lookup entirely. Resolution is now an exact membership test
against the existing frozen vocabularies via `containsValue`, which touches
no prototype method, and the value returned on a hit is the caller's own
string rather than one produced by a container. The resolver can therefore
return only the exact requested name when it is modeled, or
UNKNOWN_JOB_OPERATION. No runtime mechanism can substitute one operation
name for another.

Adds focused adversarial regression coverage under poisoned
`Map.prototype.get`, restoring the captured descriptor in a finally block:
merge stays merge, auto_merge.enable stays auto_merge.enable, shell.exec
stays unknown, source.edit stays source.edit, merge cannot reach ALLOW_ONCE,
unknown cannot reach ALLOW_ONCE, and a legitimate source.edit still
authorizes byte-identically to its unpoisoned baseline.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
LogicDuke and others added 2 commits August 16, 2026 00:22
C1-A01 — Harden operation resolution against prototype poisoning
C1-A02 (P2): `OperatorMergeAuthorization` / `operatorMergeAuthorizes`
comments and the C1 architecture document claimed stronger guarantees
than the implementation proved. The predicate proves structural binding
only: readable required fields, a literal `singleUse === true` marker,
and exact repository, pull-request, and current-HEAD SHA equality.

It does not prove operator origin, human identity, authentication,
trusted minting, signature or possession, uniqueness, one-time
consumption, or replay prevention. A plain caller-written object literal
passes, and the same record passes repeatedly because C1 has no
consumed-capability store.

Correct the claims without changing executable authorization semantics.
A `true` result is now documented as a necessary binding check, not
sufficient proof that a merge is operator-authorized; the future trusted
operator boundary / merge broker remains responsible for authenticated
operator origin, trusted minting provenance, and one-time consumption.

Two focused tests pin the limitation so the documentation cannot drift
from the implementation. Ordinary repair-job merge authority is
unchanged: still OPERATOR_REQUIRED, mayExecuteOnce=false, permit=null.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
LogicDuke and others added 3 commits August 16, 2026 03:51
External review of PR #17 (Codex and CodeRabbit, one root cause) found
that the repaired C1-A02 text still described `MergeTarget.currentHeadSha`
as if C1 observed an authoritative live repository HEAD.

It does not. `operatorMergeAuthorizes` performs no repository read, no
GitHub API call, no adapter call, and no network access. It compares
`authorization.headSha` against the caller-supplied `target.currentHeadSha`
and nothing else, so the binding is only ever as fresh and as authoritative
as the target handed to it.

Correct the claims without changing executable authorization semantics:

- `MergeTarget` fields are documented as caller-supplied input; the
  "repository's HEAD now, supplied by a trusted adapter" wording is gone.
- The predicate's guarantee is stated against the supplied target, with
  target authoritativeness and freshness listed as not proved.
- "a new HEAD requires a new operator decision" is removed. C1 requires
  only a newly matching candidate record; it cannot tell a fresh human
  decision from the same untrusted caller assembling another literal.
- The architecture document gains an explicit list of what the future
  trusted Merge Broker must do, including obtaining the authoritative
  pull-request HEAD immediately before merge and consuming the capability
  atomically.

One test title repeated the same false repository-observation claim and is
corrected; assertions are unchanged. Ordinary repair-job merge authority
remains OPERATOR_REQUIRED, mayExecuteOnce=false, permit=null.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…laims

C1-A02 — Clarify operator merge authority guarantees
`readList` obtained each authorization-list entry with an ordinary indexed
read, which walks the prototype chain. At a sparse hole that resolved whatever
a custom array prototype — or `Array.prototype` itself — carried at that
numeric key, so a value the operator never supplied could enter the trusted
`RepairJobAuthorization` snapshot as an authorized path or command class and
reach `ALLOW_ONCE` with an `ExecutionPermit` bound to the fabricated operand.

Entries are now obtained through `readOwnElement`, which gates the read behind
the module's already-captured `Object.hasOwn` and reports absence with a
module-private sentinel rather than collapsing it into `undefined`, so the list
refuses a missing element itself instead of relying on the element reader. A
sparse hole rejects the whole list: never skipped, defaulted, or filled from
the prototype chain. Dense own lists are unaffected.

The guarantee is documented at the strength the code proves. It holds for any
array whose own-property introspection is truthful; a Proxy defines the
observable result of both the own check and the read, so one that misreports
ownership can still pass an inherited value through. That widens nothing — such
a caller can supply the same value as a dense own element — and the comment and
architecture text now say so rather than claiming an atomic observation.

The sentinel is a bare object literal, so it adds no call into a mutable global
and keeps the module's captured-intrinsic discipline.

Merge stays OPERATOR_REQUIRED, auto-merge stays DENY, and C1-A01 and C1-A02 are
untouched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
C1-A03 — Reject inherited repair list elements
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant