@crewhaus/boundary-classifier 0.2.4 → 0.3.1
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/dist/index.d.ts +1 -1
- package/dist/index.js +8 -0
- package/package.json +4 -4
- package/templates/README.md +53 -0
- package/templates/scope-audit-drift.yml +67 -0
package/dist/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export declare class BoundaryClassifierError extends CrewhausError {
|
|
|
11
11
|
* Adding a new origin? Update `OriginDefaultSeverity` and the §41 doctor
|
|
12
12
|
* check at the same time.
|
|
13
13
|
*/
|
|
14
|
-
export type TrustOrigin = "user" | "mcp" | "subagent" | "channel" | "federation" | "skill" | "compaction" | "tool" | "chain";
|
|
14
|
+
export type TrustOrigin = "user" | "mcp" | "subagent" | "channel" | "federation" | "skill" | "compaction" | "tool" | "chain" | "memory";
|
|
15
15
|
export type BoundarySeverity = "block" | "warn" | "pass";
|
|
16
16
|
export type BoundaryAction = "pass" | "warn" | "redact";
|
|
17
17
|
export type ClassifyBoundaryOptions = {
|
package/dist/index.js
CHANGED
|
@@ -70,6 +70,14 @@ const ORIGIN_DEFAULT_POLICY = {
|
|
|
70
70
|
// or an event-emitting contract can plant malicious strings in event payloads
|
|
71
71
|
// that get decoded and injected into the model's context. Block by default.
|
|
72
72
|
chain: "block",
|
|
73
|
+
// Memory content (0.3.0 design §7.4): recalled wiki articles, recalled
|
|
74
|
+
// facts, and dream-synthesis output. A wiki article written in an earlier
|
|
75
|
+
// session may have absorbed attacker text (a poisoned web page STUDYed
|
|
76
|
+
// into an article, a malicious MCP response captured as a fact) — recall
|
|
77
|
+
// re-injects it across a session boundary, so it must be re-verified at
|
|
78
|
+
// read time. Block by default, same tier as "skill" (both are
|
|
79
|
+
// disk-persisted instructions-adjacent content).
|
|
80
|
+
memory: "block",
|
|
73
81
|
};
|
|
74
82
|
/**
|
|
75
83
|
* In-process LRU cache over `(sha256(content), origin)` → result. The
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crewhaus/boundary-classifier",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Pillar-3 chokepoint — classify content crossing every trust boundary (MCP / sub-agent / channel / federation / skill / compaction / tool) with origin metadata and a content-hash LRU cache",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"test": "bun test src"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@crewhaus/errors": "0.
|
|
19
|
-
"@crewhaus/prompt-injection-detector": "0.
|
|
18
|
+
"@crewhaus/errors": "0.3.1",
|
|
19
|
+
"@crewhaus/prompt-injection-detector": "0.3.1"
|
|
20
20
|
},
|
|
21
21
|
"license": "Apache-2.0",
|
|
22
22
|
"author": {
|
|
@@ -36,5 +36,5 @@
|
|
|
36
36
|
"publishConfig": {
|
|
37
37
|
"access": "public"
|
|
38
38
|
},
|
|
39
|
-
"files": ["dist", "README.md", "LICENSE", "NOTICE"]
|
|
39
|
+
"files": ["dist", "templates", "README.md", "LICENSE", "NOTICE"]
|
|
40
40
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# boundary-classifier templates
|
|
2
|
+
|
|
3
|
+
Copy-in starting points for operating the item 49 scope-audit drift watch in
|
|
4
|
+
CI. These are **templates, not active workflows** — nothing in this directory
|
|
5
|
+
runs from inside the factory repo.
|
|
6
|
+
|
|
7
|
+
Why this package hosts the template: the drift watch exists to enforce THIS
|
|
8
|
+
package's single-chokepoint invariant. The `boundary-classifier` header
|
|
9
|
+
declares that every cross-trust-domain transition must route through
|
|
10
|
+
`classifyBoundary`, and that "a new boundary that re-implements
|
|
11
|
+
classification inline (or skips it) is a security regression, not a perf
|
|
12
|
+
optimisation" — but until item 49, only the six canonical boundary sites
|
|
13
|
+
were checked, print-only, run-and-forget. The drift watch turns that
|
|
14
|
+
invariant into a baselined CI gate, so the workflow that wires it up lives
|
|
15
|
+
next to the invariant it protects (following the `templates/` convention
|
|
16
|
+
established by `compliance-controls` and `data-retention-engine`).
|
|
17
|
+
|
|
18
|
+
- [`scope-audit-drift.yml`](scope-audit-drift.yml) — GitHub Actions
|
|
19
|
+
PR-trigger template. Copy it into the factory-shaped repository's
|
|
20
|
+
`.github/workflows/` (the audit reads `packages/*/src`, so it applies to
|
|
21
|
+
the factory repo, forks, and vendored monorepos with the same layout) and
|
|
22
|
+
edit the `<PLACEHOLDER>` comments. It runs:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
crewhaus doctor --philosophy-alignment --baseline
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
on every PR that touches `packages/**` or a spec, which:
|
|
29
|
+
|
|
30
|
+
1. Re-audits the three pillars (boundary sites, tool scopes, package
|
|
31
|
+
presence) **plus** the boundary-drift detector — a conservative scan
|
|
32
|
+
for cross-trust ingress signals (raw MCP SDK imports, inbound channel
|
|
33
|
+
transports, federation peer payloads, chain content decoders) in
|
|
34
|
+
packages that never reference the classification fabric.
|
|
35
|
+
2. Diffs the findings (by stable id: hash of class + file + symbol)
|
|
36
|
+
against the last accepted baseline at
|
|
37
|
+
`.crewhaus/scope-audit/baseline.json`, and exits non-zero **only on
|
|
38
|
+
NEW findings** — legacy accepted findings never block, so the gate can
|
|
39
|
+
be adopted on a repo with known, deliberate downstream-classification
|
|
40
|
+
transports.
|
|
41
|
+
|
|
42
|
+
To (re)accept the baseline after reviewing findings:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
crewhaus doctor --philosophy-alignment --accept-baseline
|
|
46
|
+
git add -f .crewhaus/scope-audit/baseline.json # -f: .crewhaus/ is gitignored
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**The baseline must be committed.** The factory `.gitignore` excludes
|
|
50
|
+
`.crewhaus/` (runtime artifacts), so the accepted baseline needs a
|
|
51
|
+
force-add — that is deliberate: accepting findings is a reviewed,
|
|
52
|
+
history-tracked act, not a runtime side effect. A PR whose only change is
|
|
53
|
+
the baseline file IS the review surface for newly accepted findings.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# scope-audit-drift.yml — PR-gated scope-audit drift watch TEMPLATE (item 49).
|
|
2
|
+
#
|
|
3
|
+
# This is a TEMPLATE, not an active workflow: copy it into your
|
|
4
|
+
# factory-shaped repository's `.github/workflows/` and edit the
|
|
5
|
+
# <PLACEHOLDER> comments. On every PR that touches package sources or a
|
|
6
|
+
# spec, it re-runs `crewhaus doctor --philosophy-alignment --baseline`:
|
|
7
|
+
# the three-pillar audit (boundary sites, tool scopes) PLUS the
|
|
8
|
+
# boundary-drift detector, diffed against the committed baseline at
|
|
9
|
+
# `.crewhaus/scope-audit/baseline.json`. The job fails ONLY on findings
|
|
10
|
+
# that are NEW relative to the accepted baseline — a fresh cross-trust
|
|
11
|
+
# ingress that skips classifyBoundary trips the PR; the known, deliberate
|
|
12
|
+
# downstream-classified transports you already accepted do not.
|
|
13
|
+
#
|
|
14
|
+
# Prerequisites:
|
|
15
|
+
# - A committed baseline. `.crewhaus/` is gitignored in the factory repo,
|
|
16
|
+
# so accepting is an explicit, reviewed act:
|
|
17
|
+
# crewhaus doctor --philosophy-alignment --accept-baseline
|
|
18
|
+
# git add -f .crewhaus/scope-audit/baseline.json
|
|
19
|
+
# Without one, the gate fails whenever any finding exists (a gate nobody
|
|
20
|
+
# armed must not silently pass).
|
|
21
|
+
# - The audit is repo-shaped: it reads `packages/*/src`, so run it from
|
|
22
|
+
# the repository root of a factory-layout checkout.
|
|
23
|
+
|
|
24
|
+
name: scope-audit-drift
|
|
25
|
+
|
|
26
|
+
on:
|
|
27
|
+
pull_request:
|
|
28
|
+
paths:
|
|
29
|
+
# Package sources — where a new un-classified ingress would land.
|
|
30
|
+
- "packages/**"
|
|
31
|
+
# The CLI that hosts the audit itself.
|
|
32
|
+
- "apps/**"
|
|
33
|
+
# Specs: tool lists / scopes referenced by the pillar audit.
|
|
34
|
+
- "**/crewhaus.yaml"
|
|
35
|
+
# Baseline changes are exactly the review surface for accepted findings.
|
|
36
|
+
- ".crewhaus/scope-audit/baseline.json"
|
|
37
|
+
# Manual runs for baseline reviews outside a PR.
|
|
38
|
+
workflow_dispatch: {}
|
|
39
|
+
|
|
40
|
+
jobs:
|
|
41
|
+
drift-watch:
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v4
|
|
45
|
+
|
|
46
|
+
- uses: oven-sh/setup-bun@v2
|
|
47
|
+
with:
|
|
48
|
+
# <BUN-VERSION> Pin to the repo's toolchain if you pin elsewhere.
|
|
49
|
+
bun-version: latest
|
|
50
|
+
|
|
51
|
+
- name: Install workspace dependencies
|
|
52
|
+
run: bun install --frozen-lockfile
|
|
53
|
+
|
|
54
|
+
- name: Scope-audit drift gate
|
|
55
|
+
# Exit non-zero ONLY on NEW findings vs .crewhaus/scope-audit/
|
|
56
|
+
# baseline.json (legacy accepted findings never block). Add --json
|
|
57
|
+
# to also persist/emit the machine-readable snapshot + gate verdict,
|
|
58
|
+
# e.g. for uploading as a build artifact:
|
|
59
|
+
# bun apps/cli/src/index.ts doctor --philosophy-alignment --baseline --json > scope-audit.json
|
|
60
|
+
run: bun apps/cli/src/index.ts doctor --philosophy-alignment --baseline
|
|
61
|
+
|
|
62
|
+
# <ON-FAILURE> A red run means a NEW finding. Either fix the ingress
|
|
63
|
+
# (route it through classifyBoundary — see packages/boundary-classifier)
|
|
64
|
+
# or, if it is classified downstream by design, accept it in a
|
|
65
|
+
# reviewed commit:
|
|
66
|
+
# crewhaus doctor --philosophy-alignment --accept-baseline
|
|
67
|
+
# git add -f .crewhaus/scope-audit/baseline.json
|