fix: source ids#9
Merged
Merged
Conversation
Writing one probe per (identity, forbidden source) pair does not scale: N identities x M restricted sources is an N*M matrix that must be kept in sync by hand, and the forgotten cell is the one that leaks. Add an optional top-level `matrix` block that declares the authorization model once — identities, and for each source its canary and `allow` list — and deterministically expands it into ordinary v1 probes: - every identity outside a source's allow list becomes a critical deny probe (source_absent on the id + not_contains the canary); - every authorized identity becomes a medium positive control (source_present + contains the canary) that catches over-restriction and silently-empty retrieval. Expansion happens at validation time, so the runner, reporters, severities, exit codes, and redaction are unchanged, and a violated cell reports back to its source line. `matrix` and explicit `probes` can coexist. Includes matrix.boundary.yaml (authorized live template) and matrix-leak.boundary.yaml (an identity-blind index the grid catches), both wired into the release preflight, plus schema validation tests, README and examples docs, and a changelog entry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxYFd1KhMHh7ZLytLz4Yg8
Add `contextfence generate`, the deterministic codegen bridge from an authorization model to a boundary suite. It reads a connector-neutral access manifest — identities, sources, and per-source `allow` lists, the shape an IdP or permissions export produces — and emits a ready-to-edit matrix contract. - Probe keys are slugified from source ids and canaries derived from keys when omitted, so a minimal manifest still produces a complete grid. - Target and identity credentials are emitted as environment placeholders, so no secret is written to disk. - Manifest validation is line-aware and fails closed on unknown fields, invalid ids, duplicate keys, and allow entries that reference undefined identities; the generated contract is an ordinary v1 contract that gets the full validator when you run it. Live connector imports remain out of the open core, but the manifest they would produce is a stable, portable seam. Includes the generator module and CLI command, an example manifest wired into the release preflight, generator and argument-parser tests, README and examples docs, and a changelog entry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxYFd1KhMHh7ZLytLz4Yg8
There was a problem hiding this comment.
Pull request overview
This PR introduces a declarative permission matrix for boundary contracts (expanded into deterministic per-identity probes), adds deterministic contract generation from an access-manifest, and improves probe-to-YAML source mapping so generated probes can report accurate line locations.
Changes:
- Extend the contract schema to accept a
matrixblock and expand it into deny/allow probes, tracking YAML paths per probe for diagnostics. - Add
contextfence generateto convert an access manifest into a matrix-based boundary contract (plus tests and examples). - Update docs, examples, packaging, and release checks to cover the new matrix and generate workflows.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/contract/schema.ts | Adds matrix expansion, probe path tracking, and updated validation rules. |
| src/contract/parser.ts | Uses per-probe YAML paths to compute accurate probe locations. |
| src/contract/matrix.test.ts | Adds tests covering matrix expansion behavior and YAML location mapping. |
| src/contract/index.ts | Exports the new generator API/types. |
| src/contract/generate.ts | Implements access-manifest parsing and deterministic contract generation. |
| src/contract/generate.test.ts | Validates generator output round-trips through the real parser/validator. |
| src/cli/main.ts | Adds contextfence generate command wiring and output handling. |
| src/cli/args.ts | Adds generate command parsing and help text. |
| src/cli/args.test.ts | Adds coverage for generate CLI parsing and validation. |
| scripts/release-check.mjs | Extends release smoke checks to cover matrix fixtures and generate command. |
| README.md | Documents matrix contracts and the generate workflow. |
| package.json | Ensures examples/manifests are included in published artifacts. |
| examples/README.md | Adds example usage for matrix expansion and generation from manifests. |
| examples/manifests/northstar-access.yaml | Adds a sample access manifest input for contextfence generate. |
| examples/contracts/matrix.boundary.yaml | Adds a live-target example matrix contract. |
| examples/contracts/matrix-leak.boundary.yaml | Adds an intentionally failing matrix contract to demonstrate detection. |
| CHANGELOG.md | Records the new matrix feature and generate command under Unreleased. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+189
to
+192
| for (const identityId of identityIds) { | ||
| const denied = !allow.has(identityId); | ||
| if (!denied && !positiveControls) continue; | ||
| const probeId = `matrix-${key}-${identityId}-${denied ? "deny" : "allow"}`; |
Comment on lines
+155
to
+160
| if (key) { | ||
| if (seenKeys.has(key)) { | ||
| issue([...sourcePath, "key"], "matrix source key is duplicated.", "DUPLICATE_ID"); | ||
| } | ||
| seenKeys.add(key); | ||
| } |
Comment on lines
+11
to
+12
| - Declarative `matrix` block that expands an authorization model (identities, sources, per-source `allow` lists, and canaries) into the full identity × source grid of deterministic probes: a critical deny probe for every unauthorized identity and a positive control for every authorized one. Generated probes compile down to ordinary v1 probes and report against their source line. Includes `examples/contracts/matrix.boundary.yaml` and `examples/contracts/matrix-leak.boundary.yaml`. | ||
| - `contextfence generate` command that turns a connector-neutral access manifest (identities, sources, and per-source `allow` lists) into a matrix boundary contract, deriving probe keys and canaries deterministically and emitting environment placeholders for target and identity credentials. Includes `examples/manifests/northstar-access.yaml`. |
11 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes
Evidence
Verification
pnpm lintpnpm typecheckpnpm testpnpm buildSafety and compatibility
CHANGELOG.md.Screenshots or artifacts