approval-md 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -24
- package/SPEC.md +57 -11
- package/dist/src/channels/contract.d.ts +34 -1
- package/dist/src/channels/contract.js +200 -7
- package/dist/src/channels/contract.js.map +1 -1
- package/dist/src/channels/telegram.d.ts +123 -11
- package/dist/src/channels/telegram.js +218 -23
- package/dist/src/channels/telegram.js.map +1 -1
- package/dist/src/channels/web.d.ts +9 -0
- package/dist/src/channels/web.js +17 -0
- package/dist/src/channels/web.js.map +1 -1
- package/dist/src/cli/amend.js +214 -30
- package/dist/src/cli/amend.js.map +1 -1
- package/dist/src/cli/attest.d.ts +9 -0
- package/dist/src/cli/attest.js +134 -7
- package/dist/src/cli/attest.js.map +1 -1
- package/dist/src/cli/channel-telegram.d.ts +99 -26
- package/dist/src/cli/channel-telegram.js +311 -13
- package/dist/src/cli/channel-telegram.js.map +1 -1
- package/dist/src/cli/channel.d.ts +9 -0
- package/dist/src/cli/channel.js +9 -0
- package/dist/src/cli/channel.js.map +1 -1
- package/dist/src/cli/codex-bridge.d.ts +819 -0
- package/dist/src/cli/codex-bridge.js +1607 -0
- package/dist/src/cli/codex-bridge.js.map +1 -0
- package/dist/src/cli/codex.d.ts +1 -1
- package/dist/src/cli/codex.js +304 -7
- package/dist/src/cli/codex.js.map +1 -1
- package/dist/src/cli/daemon.js +4 -1
- package/dist/src/cli/daemon.js.map +1 -1
- package/dist/src/cli/doctor.js +467 -12
- package/dist/src/cli/doctor.js.map +1 -1
- package/dist/src/cli/execute.js +25 -2
- package/dist/src/cli/execute.js.map +1 -1
- package/dist/src/cli/help.d.ts +6 -2
- package/dist/src/cli/help.js +165 -60
- package/dist/src/cli/help.js.map +1 -1
- package/dist/src/cli/hook-codex.d.ts +49 -1
- package/dist/src/cli/hook-codex.js +60 -1
- package/dist/src/cli/hook-codex.js.map +1 -1
- package/dist/src/cli/hook.d.ts +459 -3
- package/dist/src/cli/hook.js +1062 -114
- package/dist/src/cli/hook.js.map +1 -1
- package/dist/src/cli/import.js +1 -1
- package/dist/src/cli/import.js.map +1 -1
- package/dist/src/cli/main.js +5 -3
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/cli/policy-apply.d.ts +195 -0
- package/dist/src/cli/policy-apply.js +573 -0
- package/dist/src/cli/policy-apply.js.map +1 -0
- package/dist/src/cli/policy.js +14 -1
- package/dist/src/cli/policy.js.map +1 -1
- package/dist/src/cli/preflight.d.ts +151 -13
- package/dist/src/cli/preflight.js +398 -41
- package/dist/src/cli/preflight.js.map +1 -1
- package/dist/src/cli/sandbox.js +17 -1
- package/dist/src/cli/sandbox.js.map +1 -1
- package/dist/src/cli/scaffold.d.ts +1 -1
- package/dist/src/cli/scaffold.js +1 -1
- package/dist/src/cli/setup-channel.d.ts +9 -0
- package/dist/src/cli/setup-channel.js +28 -1
- package/dist/src/cli/setup-channel.js.map +1 -1
- package/dist/src/cli/setup-common.d.ts +3 -1
- package/dist/src/cli/setup-common.js +3 -2
- package/dist/src/cli/setup-common.js.map +1 -1
- package/dist/src/cli/setup.d.ts +2 -0
- package/dist/src/cli/setup.js +94 -2
- package/dist/src/cli/setup.js.map +1 -1
- package/dist/src/cli/up.js +115 -51
- package/dist/src/cli/up.js.map +1 -1
- package/dist/src/cli/values.js +3 -4
- package/dist/src/cli/values.js.map +1 -1
- package/dist/src/cli/verb-registry.js +174 -9
- package/dist/src/cli/verb-registry.js.map +1 -1
- package/dist/src/cli/wordmark.d.ts +2 -2
- package/dist/src/cli/wordmark.js +2 -2
- package/dist/src/codex/broker.d.ts +229 -0
- package/dist/src/codex/broker.js +548 -0
- package/dist/src/codex/broker.js.map +1 -0
- package/dist/src/codex/runner.d.ts +178 -0
- package/dist/src/codex/runner.js +231 -0
- package/dist/src/codex/runner.js.map +1 -0
- package/dist/src/codex/serve.d.ts +56 -0
- package/dist/src/codex/serve.js +98 -0
- package/dist/src/codex/serve.js.map +1 -0
- package/dist/src/codex/workspace-commit.d.ts +219 -0
- package/dist/src/codex/workspace-commit.js +549 -0
- package/dist/src/codex/workspace-commit.js.map +1 -0
- package/dist/src/core/advance-cycle.d.ts +51 -0
- package/dist/src/core/advance-cycle.js +66 -2
- package/dist/src/core/advance-cycle.js.map +1 -1
- package/dist/src/core/agents-md.d.ts +20 -18
- package/dist/src/core/agents-md.js +33 -31
- package/dist/src/core/agents-md.js.map +1 -1
- package/dist/src/core/attest.d.ts +215 -0
- package/dist/src/core/attest.js +317 -7
- package/dist/src/core/attest.js.map +1 -1
- package/dist/src/core/audit.d.ts +18 -0
- package/dist/src/core/audit.js +13 -0
- package/dist/src/core/audit.js.map +1 -1
- package/dist/src/core/channel-owner.d.ts +213 -0
- package/dist/src/core/channel-owner.js +358 -0
- package/dist/src/core/channel-owner.js.map +1 -0
- package/dist/src/core/command-class.d.ts +154 -0
- package/dist/src/core/command-class.js +673 -20
- package/dist/src/core/command-class.js.map +1 -1
- package/dist/src/core/commit-guard.d.ts +272 -0
- package/dist/src/core/commit-guard.js +424 -0
- package/dist/src/core/commit-guard.js.map +1 -0
- package/dist/src/core/daemon-actor.d.ts +45 -0
- package/dist/src/core/daemon-actor.js +54 -0
- package/dist/src/core/daemon-actor.js.map +1 -0
- package/dist/src/core/dark-session.d.ts +109 -8
- package/dist/src/core/dark-session.js +266 -82
- package/dist/src/core/dark-session.js.map +1 -1
- package/dist/src/core/decision-refusal.d.ts +23 -2
- package/dist/src/core/decision-refusal.js +24 -2
- package/dist/src/core/decision-refusal.js.map +1 -1
- package/dist/src/core/env-file.d.ts +5 -0
- package/dist/src/core/env-file.js +60 -1
- package/dist/src/core/env-file.js.map +1 -1
- package/dist/src/core/execute.d.ts +15 -2
- package/dist/src/core/execute.js +15 -2
- package/dist/src/core/execute.js.map +1 -1
- package/dist/src/core/gate.d.ts +86 -1
- package/dist/src/core/gate.js +81 -1
- package/dist/src/core/gate.js.map +1 -1
- package/dist/src/core/gesture-refusal.d.ts +166 -0
- package/dist/src/core/gesture-refusal.js +188 -0
- package/dist/src/core/gesture-refusal.js.map +1 -0
- package/dist/src/core/harness-version.d.ts +1 -1
- package/dist/src/core/harness-version.js +3 -1
- package/dist/src/core/harness-version.js.map +1 -1
- package/dist/src/core/instance.d.ts +59 -2
- package/dist/src/core/instance.js +113 -0
- package/dist/src/core/instance.js.map +1 -1
- package/dist/src/core/log.d.ts +39 -1
- package/dist/src/core/log.js.map +1 -1
- package/dist/src/core/policy-explain.d.ts +10 -0
- package/dist/src/core/policy-explain.js +32 -0
- package/dist/src/core/policy-explain.js.map +1 -1
- package/dist/src/core/policy-load.d.ts +41 -1
- package/dist/src/core/policy-load.js +21 -3
- package/dist/src/core/policy-load.js.map +1 -1
- package/dist/src/core/policy-match.d.ts +43 -0
- package/dist/src/core/policy-match.js +52 -0
- package/dist/src/core/policy-match.js.map +1 -1
- package/dist/src/core/policy-proposal.d.ts +52 -0
- package/dist/src/core/policy-proposal.js +102 -2
- package/dist/src/core/policy-proposal.js.map +1 -1
- package/dist/src/core/protected-path-guard.d.ts +117 -4
- package/dist/src/core/protected-path-guard.js +362 -48
- package/dist/src/core/protected-path-guard.js.map +1 -1
- package/dist/src/core/question-preempted.d.ts +141 -0
- package/dist/src/core/question-preempted.js +152 -0
- package/dist/src/core/question-preempted.js.map +1 -0
- package/dist/src/core/read-scope.d.ts +172 -0
- package/dist/src/core/read-scope.js +252 -0
- package/dist/src/core/read-scope.js.map +1 -0
- package/dist/src/core/sandbox.d.ts +81 -0
- package/dist/src/core/sandbox.js +190 -1
- package/dist/src/core/sandbox.js.map +1 -1
- package/dist/src/core/sender-identity.d.ts +476 -0
- package/dist/src/core/sender-identity.js +572 -0
- package/dist/src/core/sender-identity.js.map +1 -0
- package/dist/src/core/shlex.d.ts +102 -0
- package/dist/src/core/shlex.js +159 -0
- package/dist/src/core/shlex.js.map +1 -0
- package/dist/src/core/values.d.ts +18 -8
- package/dist/src/core/values.js +36 -1
- package/dist/src/core/values.js.map +1 -1
- package/dist/src/daemon/advance.d.ts +10 -0
- package/dist/src/daemon/advance.js +25 -4
- package/dist/src/daemon/advance.js.map +1 -1
- package/dist/src/daemon/daemon.js +9 -0
- package/dist/src/daemon/daemon.js.map +1 -1
- package/dist/src/daemon/git-evidence.d.ts +2 -2
- package/dist/src/daemon/git-evidence.js +1 -1
- package/dist/src/mcp/server.js +8 -0
- package/dist/src/mcp/server.js.map +1 -1
- package/docs/cli-reference.md +932 -32
- package/docs/codex-enforced-session.md +75 -2
- package/docs/codex-workspace-broker.md +118 -0
- package/package.json +3 -1
- package/schema/event.schema.json +538 -9
- package/schema/fixtures/event/invalid/approval-granted-sender-hashed-false.json +20 -0
- package/schema/fixtures/event/invalid/approval-granted-sender-hashed-raw-id.json +20 -0
- package/schema/fixtures/event/invalid/audit-gesture-refused-human-actor.json +16 -0
- package/schema/fixtures/event/invalid/audit-gesture-refused-no-actor-no-sender.json +15 -0
- package/schema/fixtures/event/invalid/audit-gesture-refused-unknown-gesture.json +16 -0
- package/schema/fixtures/event/invalid/audit-question-preempted-agent-actor.json +16 -0
- package/schema/fixtures/event/invalid/audit-question-preempted-no-question-id.json +16 -0
- package/schema/fixtures/event/invalid/audit-question-preempted-unknown-source.json +15 -0
- package/schema/fixtures/event/invalid/gate-path-signed-off-absolute-path.json +14 -0
- package/schema/fixtures/event/invalid/gate-path-signed-off-agent-actor.json +14 -0
- package/schema/fixtures/event/invalid/gate-path-signed-off-missing-path.json +13 -0
- package/schema/fixtures/event/valid/approval-granted-sender-hashed.json +20 -0
- package/schema/fixtures/event/valid/audit-gesture-refused-review-note.json +21 -0
- package/schema/fixtures/event/valid/audit-gesture-refused-sender-key-unavailable.json +19 -0
- package/schema/fixtures/event/valid/audit-gesture-refused.json +19 -0
- package/schema/fixtures/event/valid/audit-question-preempted-no-verdict.json +16 -0
- package/schema/fixtures/event/valid/audit-question-preempted.json +20 -0
- package/schema/fixtures/event/valid/gate-path-signed-off.json +14 -0
- package/schema/fixtures/event/valid/harness-kind-claude-code.json +23 -0
- package/schema/fixtures/event/valid/harness-kind-codex.json +23 -0
- package/schema/fixtures/event/valid/harness-kind-cursor.json +23 -0
- package/schema/fixtures/event/valid/harness-kind-grok.json +23 -0
- package/schema/fixtures/event/valid/harness-kind-muse.json +23 -0
- package/schema/fixtures/policy/invalid/senders-half-keyed.json +20 -0
- package/schema/fixtures/policy/valid/canonical.json +1 -1
- package/schema/fixtures/policy/valid/senders-keyed.json +24 -0
- package/schema/fixtures/policy-md/valid/canonical.md +1 -1
- package/schema/fixtures/policy-md/valid/with-values.md +5 -7
- package/schema/fixtures/values/invalid/class-shaped.json +1 -1
- package/schema/fixtures/values/invalid/duplicate-entry.json +1 -1
- package/schema/fixtures/values/invalid/non-string-item.json +1 -1
- package/schema/fixtures/values/invalid/over-cap.json +1 -1
- package/schema/fixtures/values/invalid/unknown-key.json +1 -1
- package/schema/fixtures/values/invalid/version-float.json +1 -0
- package/schema/fixtures/values/invalid/version-integer.json +1 -0
- package/schema/fixtures/values/invalid/version-wrong-string.json +1 -0
- package/schema/fixtures/values/valid/empty-lists.json +2 -3
- package/schema/fixtures/values/valid/full.json +5 -7
- package/schema/fixtures/values/valid/minimal.json +1 -1
- package/schema/fixtures/values-md/invalid/schema-invalid.md +5 -3
- package/schema/fixtures/values-md/invalid/two-blocks.md +3 -3
- package/schema/fixtures/values-md/invalid/unterminated.md +2 -2
- package/schema/fixtures/values-md/invalid/version-1.md +69 -0
- package/schema/fixtures/values-md/invalid/version-unquoted.md +64 -0
- package/schema/fixtures/values-md/invalid/yaml-error.md +2 -2
- package/schema/fixtures/values-md/valid/absent.md +1 -1
- package/schema/fixtures/values-md/valid/with-values.md +5 -7
- package/schema/policy.schema.json +54 -2
- package/schema/values.schema.json +7 -11
- package/schema/fixtures/values/invalid/version-string.json +0 -1
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The unit of judgment: one commit (APRV-375).
|
|
3
|
+
*
|
|
4
|
+
* ## What a grant binds
|
|
5
|
+
*
|
|
6
|
+
* A `policy.edit` grant binds ONE edit: a before-state, an after-state, and a
|
|
7
|
+
* human who was shown them. The protected-path guard of
|
|
8
|
+
* `core/protected-path-guard.ts` decides whether a change is made of such
|
|
9
|
+
* material, and everything it answers is relative to the pair of blobs the
|
|
10
|
+
* caller hands it. So the caller's choice of pair is the whole question, and
|
|
11
|
+
* until this module the CI guard chose the pull request's COMBINED diff: base
|
|
12
|
+
* tree against head tree, every commit's work replayed as one change.
|
|
13
|
+
*
|
|
14
|
+
* That pairing has no grant. PR #427 is the worked example (APRV-357's
|
|
15
|
+
* reproduction, PR #452): three lane commits, each granted, plus two merges of
|
|
16
|
+
* `origin/main` made while four other lanes were editing `SPEC.md`. Replayed as
|
|
17
|
+
* one change it failed `uncovered-hunk` with fourteen uncovered lines, twenty
|
|
18
|
+
* nine records naming the path and twenty seven covering part of it, because a
|
|
19
|
+
* grant binds a before-state that the combined base no longer carries once an
|
|
20
|
+
* earlier commit in the range has moved those bytes. Replayed per commit all
|
|
21
|
+
* three pass, in well under a second each.
|
|
22
|
+
*
|
|
23
|
+
* `approval doctor`'s dark-session arm A reached the same conclusion from the
|
|
24
|
+
* other side (APRV-369): it used to replay a whole window as one change and
|
|
25
|
+
* failed a change CI had passed, at every session start. It now replays per
|
|
26
|
+
* commit. This module is where the two meet, so the agreement is by
|
|
27
|
+
* construction rather than by two code paths kept in step.
|
|
28
|
+
*
|
|
29
|
+
* ## The security argument
|
|
30
|
+
*
|
|
31
|
+
* Judging per commit asks a SMALLER question than judging the combined diff, so
|
|
32
|
+
* it owes an argument that nothing escapes. It is this:
|
|
33
|
+
*
|
|
34
|
+
* 1. Every byte that differs between the base tree and the head tree was
|
|
35
|
+
* written by some commit in `base..head`. Two-dot range semantics is what
|
|
36
|
+
* makes that true: a commit reachable from base is excluded, and a commit
|
|
37
|
+
* reachable from base changed nothing about the difference between the two
|
|
38
|
+
* trees that its own history did not already carry.
|
|
39
|
+
* 2. A non-merge commit's whole contribution is its diff against its parent,
|
|
40
|
+
* which is exactly what this module hands the guard.
|
|
41
|
+
* 3. A merge commit contributes only what it resolved: the bytes its result
|
|
42
|
+
* carries that no parent carried. That is git's DENSE combined diff
|
|
43
|
+
* (`--cc`), and a merge with a non-empty one on a guarded path is judged
|
|
44
|
+
* against its first parent here. A merge whose result on a path is some
|
|
45
|
+
* parent's bytes verbatim invented nothing and is listed as skipped.
|
|
46
|
+
*
|
|
47
|
+
* Together: every changed byte is inside some judged unit, and each unit is
|
|
48
|
+
* judged against the before-state a grant for it would have bound. The guard
|
|
49
|
+
* stops asking about the combined diff because the combined diff is a change
|
|
50
|
+
* nobody ever made and nobody could have approved.
|
|
51
|
+
*
|
|
52
|
+
* ## One thing is NOT per commit: whole-file evidence
|
|
53
|
+
*
|
|
54
|
+
* A grant binds a hunk, so it is evidence about one commit. A sign-off
|
|
55
|
+
* (APRV-338), an organ attestation (APRV-272) and the policy attestation say a
|
|
56
|
+
* human read the file AS IT NOW STANDS, so they are evidence about the bytes
|
|
57
|
+
* the range INSTALLS: every commit is offered the digests at the RANGE HEAD.
|
|
58
|
+
* {@link digestsAt} carries the reasoning, and it matters because matching them
|
|
59
|
+
* per commit would have repealed the escape hatch for every edit before the
|
|
60
|
+
* last one.
|
|
61
|
+
*
|
|
62
|
+
* ## What this does NOT do
|
|
63
|
+
*
|
|
64
|
+
* It does not re-judge work the branch absorbed by merging `origin/main`. Those
|
|
65
|
+
* commits are main's, they passed their own pull requests, and two-dot
|
|
66
|
+
* `base..head` excludes them by construction: CI computes base as `git
|
|
67
|
+
* merge-base origin/main HEAD`, so a branch that merged main has every absorbed
|
|
68
|
+
* commit reachable from base. Nothing is skipped by a rule about authorship or
|
|
69
|
+
* about who pushed what; the range is simply the commits this pull request is
|
|
70
|
+
* proposing to add.
|
|
71
|
+
*
|
|
72
|
+
* It also does not relax the exact-replay byte budget of
|
|
73
|
+
* `core/protected-path-guard.ts`. Per commit that budget is not reached in any
|
|
74
|
+
* case observed, which is why APRV-357 closes as superseded rather than fixed.
|
|
75
|
+
*/
|
|
76
|
+
import { createHash } from "node:crypto";
|
|
77
|
+
import { evaluateProtectedPaths, isGuardedPath } from "./protected-path-guard.js";
|
|
78
|
+
/** SHA-256 of a UTF-8 string, hex. */
|
|
79
|
+
function sha256Hex(text) {
|
|
80
|
+
return createHash("sha256").update(text, "utf8").digest("hex");
|
|
81
|
+
}
|
|
82
|
+
/** Is this commit a merge? */
|
|
83
|
+
export function isMerge(commit) {
|
|
84
|
+
return commit.parents.length > 1;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The revision a commit is judged AGAINST: its first parent.
|
|
88
|
+
*
|
|
89
|
+
* First parent and not the merge base of the parents, for a merge, because the
|
|
90
|
+
* first parent is the state the branch was in before the merge and the merge's
|
|
91
|
+
* own contribution is measured from there. `null` for a root commit, which has
|
|
92
|
+
* no before-state at all and whose every path is an add.
|
|
93
|
+
*/
|
|
94
|
+
export function baseRevOf(commit) {
|
|
95
|
+
return commit.parents.length === 0 ? null : `${commit.sha}^1`;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Record and field separators inside `git log --pretty`.
|
|
99
|
+
*
|
|
100
|
+
* ASCII 30 and 31, for the reason `core/dark-session.ts` states where it uses
|
|
101
|
+
* the same pair: git quotes any path containing a control character, so a
|
|
102
|
+
* filename engineered to carry one arrives escaped and cannot forge a commit
|
|
103
|
+
* boundary in output the guard parses.
|
|
104
|
+
*/
|
|
105
|
+
const RS = "";
|
|
106
|
+
const FS = "";
|
|
107
|
+
function datesOf(author, committer) {
|
|
108
|
+
const a = author === undefined || author.length === 0 ? null : author;
|
|
109
|
+
const c = committer === undefined || committer.length === 0 ? null : committer;
|
|
110
|
+
return { author: a, committer: c ?? a };
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The commits of `base..head`, oldest first, each with the paths it is judged
|
|
114
|
+
* for.
|
|
115
|
+
*
|
|
116
|
+
* `judged` narrows the per-path work a MERGE costs: git's dense combined diff
|
|
117
|
+
* has to be asked for one path at a time (see below), and asking it about every
|
|
118
|
+
* file a large merge touched would be a git invocation per file for no verdict.
|
|
119
|
+
* A non-merge commit's path list is not narrowed at all, so the guard still
|
|
120
|
+
* reports exempt paths and still sees everything it might protect.
|
|
121
|
+
*
|
|
122
|
+
* The two-step merge question is not an optimization, it is correctness.
|
|
123
|
+
* `git log -c --name-only` lists the files "modified from all parents", which
|
|
124
|
+
* OVER-reports: at PR #427's merge `e66ba9e` it lists `SPEC.md`, whose result
|
|
125
|
+
* differs from both parents as a blob while every hunk of it came verbatim from
|
|
126
|
+
* one side. The dense (`--cc`) rendering is the one that drops hunks a parent
|
|
127
|
+
* already carried, and a path whose dense rendering is empty invented nothing.
|
|
128
|
+
* So each candidate is re-asked with a per-path `--cc` patch, and passing the
|
|
129
|
+
* path as a pathspec rather than parsing it out of a `diff --cc` header keeps
|
|
130
|
+
* quoted and unusual filenames out of the parser entirely.
|
|
131
|
+
*/
|
|
132
|
+
export function listCommits(read, base, head, judged) {
|
|
133
|
+
const log = read([
|
|
134
|
+
"log",
|
|
135
|
+
"--reverse",
|
|
136
|
+
`--pretty=format:${RS}%H${FS}%P${FS}%aI${FS}%cI`,
|
|
137
|
+
"--name-only",
|
|
138
|
+
`${base}..${head}`,
|
|
139
|
+
]);
|
|
140
|
+
if (log === null) {
|
|
141
|
+
return { ok: false, message: `\`git log ${base}..${head}\` failed` };
|
|
142
|
+
}
|
|
143
|
+
const commits = [];
|
|
144
|
+
for (const chunk of log.split(RS)) {
|
|
145
|
+
const lines = chunk.split("\n").filter((line) => line.length > 0);
|
|
146
|
+
const header = lines.shift();
|
|
147
|
+
if (header === undefined)
|
|
148
|
+
continue;
|
|
149
|
+
const [sha, parents, authored, committed] = header.split(FS);
|
|
150
|
+
if (sha === undefined || sha.length === 0)
|
|
151
|
+
continue;
|
|
152
|
+
const parentList = (parents ?? "")
|
|
153
|
+
.split(" ")
|
|
154
|
+
.map((part) => part.trim())
|
|
155
|
+
.filter((part) => part.length > 0);
|
|
156
|
+
const commit = {
|
|
157
|
+
sha,
|
|
158
|
+
parents: parentList,
|
|
159
|
+
ts: datesOf(authored, committed),
|
|
160
|
+
// `--name-only` reports nothing for a merge; the dense pass below fills it.
|
|
161
|
+
changedPaths: parentList.length > 1 ? denseCombinedPaths(read, sha, judged) : lines,
|
|
162
|
+
};
|
|
163
|
+
commits.push(commit);
|
|
164
|
+
}
|
|
165
|
+
return { ok: true, commits };
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* The guarded paths a merge commit's result carries that no parent carried:
|
|
169
|
+
* the merge's own work, which is what an evil merge is made of.
|
|
170
|
+
*
|
|
171
|
+
* EXPORTED because arm A of `core/dark-session.ts` asks the same question of a
|
|
172
|
+
* merge it finds on main (APRV-374), and two implementations of "what did this
|
|
173
|
+
* merge invent" would be two things to keep in step — the disagreement APRV-369
|
|
174
|
+
* was filed about. The observer there lists a window rather than a range, so it
|
|
175
|
+
* cannot reuse {@link listCommits}; it reuses this.
|
|
176
|
+
*
|
|
177
|
+
* The two-step shape is the correctness (see {@link listCommits}): `-c
|
|
178
|
+
* --name-only` gives candidates and over-reports, and the per-path `--cc` patch
|
|
179
|
+
* is the discriminator, empty for every merge whose every hunk came from a
|
|
180
|
+
* parent verbatim.
|
|
181
|
+
*/
|
|
182
|
+
export function denseCombinedPaths(read, sha, judged) {
|
|
183
|
+
const listed = read(["log", "-1", "-c", "--name-only", "--pretty=format:", sha]);
|
|
184
|
+
if (listed === null)
|
|
185
|
+
return [];
|
|
186
|
+
const dense = [];
|
|
187
|
+
for (const line of listed.split("\n")) {
|
|
188
|
+
const path = line.trim();
|
|
189
|
+
if (path.length === 0 || !judged(path))
|
|
190
|
+
continue;
|
|
191
|
+
const patch = read(["log", "-1", "--cc", "--pretty=format:", sha, "--", path]);
|
|
192
|
+
if (patch !== null && patch.trim().length > 0)
|
|
193
|
+
dense.push(path);
|
|
194
|
+
}
|
|
195
|
+
return dense;
|
|
196
|
+
}
|
|
197
|
+
export function commitGuardInputParts(read, commit) {
|
|
198
|
+
const parents = commit.parents;
|
|
199
|
+
const baseRev = parents !== undefined && parents.length === 0 ? null : `${commit.sha}^1`;
|
|
200
|
+
const blobCache = new Map();
|
|
201
|
+
const digestCache = new Map();
|
|
202
|
+
const inTree = (rev, path) => {
|
|
203
|
+
const listed = read(["ls-tree", "--name-only", rev, "--", path]);
|
|
204
|
+
return listed !== null && listed.trim().length > 0;
|
|
205
|
+
};
|
|
206
|
+
const show = (rev, path) => read(["show", `${rev}:${path}`]);
|
|
207
|
+
return {
|
|
208
|
+
blobsFor: (path) => {
|
|
209
|
+
const cached = blobCache.get(path);
|
|
210
|
+
if (cached !== undefined)
|
|
211
|
+
return cached;
|
|
212
|
+
const baseHas = baseRev !== null && inTree(baseRev, path);
|
|
213
|
+
const headHas = inTree(commit.sha, path);
|
|
214
|
+
const baseText = baseHas && baseRev !== null ? show(baseRev, path) : null;
|
|
215
|
+
const headText = headHas ? show(commit.sha, path) : null;
|
|
216
|
+
// A blob git cannot show, or one with a NUL byte in it, answers null and
|
|
217
|
+
// the guard fails the path `change-unreadable` rather than falling back
|
|
218
|
+
// to the path-level rule. The fallback is the hole (APRV-202).
|
|
219
|
+
const unreadable = (baseHas && baseText === null) ||
|
|
220
|
+
(headHas && headText === null) ||
|
|
221
|
+
(baseText !== null && baseText.includes("")) ||
|
|
222
|
+
(headText !== null && headText.includes(""));
|
|
223
|
+
const value = unreadable ? null : { base: baseText, head: headText };
|
|
224
|
+
blobCache.set(path, value);
|
|
225
|
+
return value;
|
|
226
|
+
},
|
|
227
|
+
sha256At: (path) => {
|
|
228
|
+
const cached = digestCache.get(path);
|
|
229
|
+
if (cached !== undefined)
|
|
230
|
+
return cached;
|
|
231
|
+
const blob = show(commit.sha, path);
|
|
232
|
+
const value = blob === null ? null : sha256Hex(blob);
|
|
233
|
+
digestCache.set(path, value);
|
|
234
|
+
return value;
|
|
235
|
+
},
|
|
236
|
+
changeTsFor: () => commit.ts,
|
|
237
|
+
window: {
|
|
238
|
+
base: baseRev === null ? "(root)" : `${commit.sha.slice(0, 12)}^1`,
|
|
239
|
+
head: commit.sha.slice(0, 12),
|
|
240
|
+
},
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* SHA-256 of any path's bytes AT ONE REVISION, cached.
|
|
245
|
+
*
|
|
246
|
+
* ## Why whole-file evidence is matched at the range head and not per commit
|
|
247
|
+
*
|
|
248
|
+
* The two kinds of evidence answer different questions, so they are anchored to
|
|
249
|
+
* different things:
|
|
250
|
+
*
|
|
251
|
+
* - A GRANT binds a hunk — a before-state, an after-state, a human who was
|
|
252
|
+
* shown them — so it is evidence about ONE COMMIT and is matched per commit,
|
|
253
|
+
* which is what APRV-375 is about.
|
|
254
|
+
* - A SIGN-OFF (`gate.path.signed_off`, APRV-338), an ORGAN attestation
|
|
255
|
+
* (`gate.organ.attested`, APRV-272) and the POLICY attestation
|
|
256
|
+
* (`policy.updated`) are whole-file records: a human read the file AS IT NOW
|
|
257
|
+
* STANDS and ratified those exact bytes. What they are about is the bytes the
|
|
258
|
+
* pull request INSTALLS, which is the blob at the range head.
|
|
259
|
+
*
|
|
260
|
+
* Matching them per commit would have quietly repealed the escape hatch. A
|
|
261
|
+
* two-commit branch whose first commit has no grant could no longer be rescued
|
|
262
|
+
* by a sign-off at head, because the intermediate blob is not the ratified one;
|
|
263
|
+
* a policy amendment split over two commits would fail on the first. So every
|
|
264
|
+
* commit in a range is offered the digests at the range head, whatever its own
|
|
265
|
+
* blob hashes to. The ordering APRV-338 asked for is untouched: the evaluator
|
|
266
|
+
* reaches the sign-off only after every grant search has failed, so hunk
|
|
267
|
+
* evidence still leads the reasons wherever it exists.
|
|
268
|
+
*/
|
|
269
|
+
export function digestsAt(read, rev) {
|
|
270
|
+
const cache = new Map();
|
|
271
|
+
return (path) => {
|
|
272
|
+
const cached = cache.get(path);
|
|
273
|
+
if (cached !== undefined)
|
|
274
|
+
return cached;
|
|
275
|
+
const blob = read(["show", `${rev}:${path}`]);
|
|
276
|
+
const value = blob === null ? null : sha256Hex(blob);
|
|
277
|
+
cache.set(path, value);
|
|
278
|
+
return value;
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Judge every commit of `base..head` on its own records, and report the
|
|
283
|
+
* conjunction.
|
|
284
|
+
*
|
|
285
|
+
* `evaluateProtectedPaths` is unchanged and is what decides each commit: this
|
|
286
|
+
* function chooses the unit and nothing else. A commit that changed no guarded
|
|
287
|
+
* path costs one evaluator call that finds nothing, and a clean merge costs no
|
|
288
|
+
* evaluator call at all.
|
|
289
|
+
*/
|
|
290
|
+
export function judgeCommits(options) {
|
|
291
|
+
const { read, base, head, shared } = options;
|
|
292
|
+
const empty = {
|
|
293
|
+
ok: false,
|
|
294
|
+
commits: [],
|
|
295
|
+
findings: [],
|
|
296
|
+
exempt: [],
|
|
297
|
+
window: shared.window,
|
|
298
|
+
};
|
|
299
|
+
const listed = listCommits(read, base, head, (path) => isJudgedPath(path, shared));
|
|
300
|
+
if (!listed.ok)
|
|
301
|
+
return { ...empty, unavailable: listed.message };
|
|
302
|
+
// Whole-file evidence is about the bytes this pull request INSTALLS, so it is
|
|
303
|
+
// matched at the RANGE head for every commit in the range. See {@link digestsAt}.
|
|
304
|
+
const atRangeHead = digestsAt(read, head);
|
|
305
|
+
const policySha256AtHead = atRangeHead(shared.policyPath);
|
|
306
|
+
const commits = [];
|
|
307
|
+
const findings = [];
|
|
308
|
+
const exempt = new Set();
|
|
309
|
+
for (const commit of listed.commits) {
|
|
310
|
+
const merge = isMerge(commit);
|
|
311
|
+
const baseRev = baseRevOf(commit);
|
|
312
|
+
if (commit.changedPaths.length === 0) {
|
|
313
|
+
commits.push({
|
|
314
|
+
sha: commit.sha,
|
|
315
|
+
base: baseRev,
|
|
316
|
+
merge,
|
|
317
|
+
judged: false,
|
|
318
|
+
skipped: merge ? "clean-merge" : "no-guarded-path",
|
|
319
|
+
ok: true,
|
|
320
|
+
findings: [],
|
|
321
|
+
exempt: [],
|
|
322
|
+
covered: [],
|
|
323
|
+
});
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
const parts = commitGuardInputParts(read, commit);
|
|
327
|
+
const report = evaluateProtectedPaths({
|
|
328
|
+
...shared,
|
|
329
|
+
policySha256AtHead,
|
|
330
|
+
changedPaths: [...commit.changedPaths].sort(),
|
|
331
|
+
blobsFor: parts.blobsFor,
|
|
332
|
+
organSha256AtHead: atRangeHead,
|
|
333
|
+
pathSha256AtHead: atRangeHead,
|
|
334
|
+
changeTsFor: parts.changeTsFor,
|
|
335
|
+
window: { ...shared.window, base: parts.window.base, head: parts.window.head },
|
|
336
|
+
});
|
|
337
|
+
for (const path of report.exempt)
|
|
338
|
+
exempt.add(path);
|
|
339
|
+
for (const finding of report.findings)
|
|
340
|
+
findings.push({ ...finding, commit: commit.sha });
|
|
341
|
+
const covered = [];
|
|
342
|
+
for (const finding of report.findings) {
|
|
343
|
+
if (!finding.ok)
|
|
344
|
+
continue;
|
|
345
|
+
for (const seq of finding.coveredBy ?? (finding.seq === undefined ? [] : [finding.seq])) {
|
|
346
|
+
if (!covered.includes(seq))
|
|
347
|
+
covered.push(seq);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
const nothingToJudge = report.findings.length === 0 && report.exempt.length === 0;
|
|
351
|
+
commits.push({
|
|
352
|
+
sha: commit.sha,
|
|
353
|
+
base: baseRev,
|
|
354
|
+
merge,
|
|
355
|
+
judged: !nothingToJudge,
|
|
356
|
+
skipped: nothingToJudge ? (merge ? "clean-merge" : "no-guarded-path") : null,
|
|
357
|
+
ok: report.ok,
|
|
358
|
+
findings: report.findings,
|
|
359
|
+
exempt: report.exempt,
|
|
360
|
+
covered,
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
return {
|
|
364
|
+
ok: commits.every((commit) => commit.ok),
|
|
365
|
+
commits,
|
|
366
|
+
findings,
|
|
367
|
+
exempt: [...exempt],
|
|
368
|
+
window: shared.window,
|
|
369
|
+
unavailable: null,
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Would the guard have an opinion about this path?
|
|
374
|
+
*
|
|
375
|
+
* Only used to keep the merge pass cheap, so it is deliberately the PERMISSIVE
|
|
376
|
+
* side of the question: the policy's widening entries plus the built-in set,
|
|
377
|
+
* which is what `isGuardedPath` asks. A path this answers `true` for still has
|
|
378
|
+
* to earn its verdict from the evaluator.
|
|
379
|
+
*/
|
|
380
|
+
function isJudgedPath(path, shared) {
|
|
381
|
+
return isGuardedPath(path, shared.policyProtectedPaths);
|
|
382
|
+
}
|
|
383
|
+
/** The report as the lines CI prints. Pure. */
|
|
384
|
+
export function renderCommitGuardReport(report) {
|
|
385
|
+
const lines = [];
|
|
386
|
+
const judged = report.commits.filter((commit) => commit.judged);
|
|
387
|
+
lines.push(`protected-path guard: ${report.window.base}..${report.window.head}, judged one commit at a time (${String(report.commits.length)} commit(s) in the range, ${String(judged.length)} with a protected change)`);
|
|
388
|
+
if (report.unavailable !== null) {
|
|
389
|
+
lines.push(` the guard could not look: ${report.unavailable}`);
|
|
390
|
+
return `${lines.join("\n")}\n`;
|
|
391
|
+
}
|
|
392
|
+
if (report.exempt.length > 0) {
|
|
393
|
+
lines.push(` exempt (the daemon's own append surface, evidence rather than a protected write): ${report.exempt.join(", ")}`);
|
|
394
|
+
}
|
|
395
|
+
if (report.commits.length === 0) {
|
|
396
|
+
lines.push(" no commits in the range");
|
|
397
|
+
return `${lines.join("\n")}\n`;
|
|
398
|
+
}
|
|
399
|
+
for (const commit of report.commits) {
|
|
400
|
+
const sha = commit.sha.slice(0, 12);
|
|
401
|
+
const against = commit.base === null ? "a root commit" : `base ${sha}^1`;
|
|
402
|
+
if (!commit.judged) {
|
|
403
|
+
const why = commit.skipped === "clean-merge"
|
|
404
|
+
? "merge, and its result on every guarded path is one parent's bytes verbatim"
|
|
405
|
+
: "no protected path changed";
|
|
406
|
+
lines.push(` SKIP ${sha} (${against}): ${why}`);
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
const covered = commit.covered.length === 0
|
|
410
|
+
? ""
|
|
411
|
+
: `, covered by seq ${commit.covered.slice(0, 8).join(", ")}${commit.covered.length > 8 ? ", …" : ""}`;
|
|
412
|
+
lines.push(` ${commit.ok ? "PASS" : "FAIL"} ${sha} (${against})${commit.merge ? ", merge resolution" : ""}${covered}`);
|
|
413
|
+
for (const finding of commit.findings) {
|
|
414
|
+
lines.push(finding.ok
|
|
415
|
+
? ` PASS ${finding.path} [${finding.evidence}]`
|
|
416
|
+
: ` FAIL ${finding.path} [${finding.code}]`);
|
|
417
|
+
lines.push(` ${finding.detail}`);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
if (judged.length === 0)
|
|
421
|
+
lines.push(" no protected paths changed");
|
|
422
|
+
return `${lines.join("\n")}\n`;
|
|
423
|
+
}
|
|
424
|
+
//# sourceMappingURL=commit-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commit-guard.js","sourceRoot":"","sources":["../../../src/core/commit-guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Is THIS process the daemon? (APRV-382.)
|
|
3
|
+
*
|
|
4
|
+
* One fact, held in one place, so the gated advance path can ask it without
|
|
5
|
+
* being told it. `log.advance.daemon` is autonomous in this repository's policy
|
|
6
|
+
* and `log.advance` is not, which means something has to decide which of the
|
|
7
|
+
* two a cycle asks under — and that decision must not be an argument a caller
|
|
8
|
+
* passes, because a field a caller sets is a self-reported field, and SPEC.md
|
|
9
|
+
* §11.1 invariant 4 says a self-reported field never reduces scrutiny.
|
|
10
|
+
*
|
|
11
|
+
* So the mark is set by the daemon runtime itself, at construction, and read
|
|
12
|
+
* from module state that no exported function will set on another process's
|
|
13
|
+
* behalf: {@link markDaemonProcess} takes no arguments and records
|
|
14
|
+
* `process.pid`, and {@link isDaemonProcess} answers true only while that
|
|
15
|
+
* recorded pid is still this process's own. A child inherits nothing — module
|
|
16
|
+
* state does not cross a `spawn` — so the advance child, which holds no
|
|
17
|
+
* authority by design, answers false here as it should.
|
|
18
|
+
*
|
|
19
|
+
* What this is NOT: a security boundary against code already running in the
|
|
20
|
+
* daemon's process. Anything executing there can call {@link markDaemonProcess}
|
|
21
|
+
* the way the daemon does. The boundary that keeps an agent out of this process
|
|
22
|
+
* is elsewhere and unchanged: `approval daemon run` and `approval up` classify
|
|
23
|
+
* `gate.self`, which this repository's policy leaves at the fail-closed manual
|
|
24
|
+
* default, so an agent cannot start a daemon unattended in the first place.
|
|
25
|
+
* What this module removes is the smaller and likelier failure — a future
|
|
26
|
+
* caller wiring the autonomous route through a struct field, in a session, by
|
|
27
|
+
* accident.
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Declare this process the daemon runtime. Called by the daemon, and only by it.
|
|
31
|
+
*
|
|
32
|
+
* Idempotent, and argument-free on purpose: there is no spelling of this call
|
|
33
|
+
* that marks a process other than the caller's own.
|
|
34
|
+
*/
|
|
35
|
+
export declare function markDaemonProcess(): void;
|
|
36
|
+
/**
|
|
37
|
+
* Forget the mark. For tests, and for a runtime that stops being a daemon.
|
|
38
|
+
*
|
|
39
|
+
* Present so a suite can exercise both actors in one file without a second
|
|
40
|
+
* process. Clearing is always the STRICTER direction — an unmarked process
|
|
41
|
+
* takes the supervised route — so nothing widens by calling it.
|
|
42
|
+
*/
|
|
43
|
+
export declare function clearDaemonProcess(): void;
|
|
44
|
+
/** Is this process the daemon runtime? */
|
|
45
|
+
export declare function isDaemonProcess(): boolean;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Is THIS process the daemon? (APRV-382.)
|
|
3
|
+
*
|
|
4
|
+
* One fact, held in one place, so the gated advance path can ask it without
|
|
5
|
+
* being told it. `log.advance.daemon` is autonomous in this repository's policy
|
|
6
|
+
* and `log.advance` is not, which means something has to decide which of the
|
|
7
|
+
* two a cycle asks under — and that decision must not be an argument a caller
|
|
8
|
+
* passes, because a field a caller sets is a self-reported field, and SPEC.md
|
|
9
|
+
* §11.1 invariant 4 says a self-reported field never reduces scrutiny.
|
|
10
|
+
*
|
|
11
|
+
* So the mark is set by the daemon runtime itself, at construction, and read
|
|
12
|
+
* from module state that no exported function will set on another process's
|
|
13
|
+
* behalf: {@link markDaemonProcess} takes no arguments and records
|
|
14
|
+
* `process.pid`, and {@link isDaemonProcess} answers true only while that
|
|
15
|
+
* recorded pid is still this process's own. A child inherits nothing — module
|
|
16
|
+
* state does not cross a `spawn` — so the advance child, which holds no
|
|
17
|
+
* authority by design, answers false here as it should.
|
|
18
|
+
*
|
|
19
|
+
* What this is NOT: a security boundary against code already running in the
|
|
20
|
+
* daemon's process. Anything executing there can call {@link markDaemonProcess}
|
|
21
|
+
* the way the daemon does. The boundary that keeps an agent out of this process
|
|
22
|
+
* is elsewhere and unchanged: `approval daemon run` and `approval up` classify
|
|
23
|
+
* `gate.self`, which this repository's policy leaves at the fail-closed manual
|
|
24
|
+
* default, so an agent cannot start a daemon unattended in the first place.
|
|
25
|
+
* What this module removes is the smaller and likelier failure — a future
|
|
26
|
+
* caller wiring the autonomous route through a struct field, in a session, by
|
|
27
|
+
* accident.
|
|
28
|
+
*/
|
|
29
|
+
/** The pid of the process that declared itself the daemon, or `null`. */
|
|
30
|
+
let daemonPid = null;
|
|
31
|
+
/**
|
|
32
|
+
* Declare this process the daemon runtime. Called by the daemon, and only by it.
|
|
33
|
+
*
|
|
34
|
+
* Idempotent, and argument-free on purpose: there is no spelling of this call
|
|
35
|
+
* that marks a process other than the caller's own.
|
|
36
|
+
*/
|
|
37
|
+
export function markDaemonProcess() {
|
|
38
|
+
daemonPid = process.pid;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Forget the mark. For tests, and for a runtime that stops being a daemon.
|
|
42
|
+
*
|
|
43
|
+
* Present so a suite can exercise both actors in one file without a second
|
|
44
|
+
* process. Clearing is always the STRICTER direction — an unmarked process
|
|
45
|
+
* takes the supervised route — so nothing widens by calling it.
|
|
46
|
+
*/
|
|
47
|
+
export function clearDaemonProcess() {
|
|
48
|
+
daemonPid = null;
|
|
49
|
+
}
|
|
50
|
+
/** Is this process the daemon runtime? */
|
|
51
|
+
export function isDaemonProcess() {
|
|
52
|
+
return daemonPid !== null && daemonPid === process.pid;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=daemon-actor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon-actor.js","sourceRoot":"","sources":["../../../src/core/daemon-actor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,yEAAyE;AACzE,IAAI,SAAS,GAAkB,IAAI,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB;IAC/B,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC;AAC1B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB;IAChC,SAAS,GAAG,IAAI,CAAC;AACnB,CAAC;AAED,0CAA0C;AAC1C,MAAM,UAAU,eAAe;IAC7B,OAAO,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,OAAO,CAAC,GAAG,CAAC;AACzD,CAAC"}
|