-
Notifications
You must be signed in to change notification settings - Fork 1
feat: enforce CAC admissibility gate and CACert pipeline #23620
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
BrianCLong
wants to merge
1
commit into
main
Choose a base branch
from
codex/bind-cac-into-ci/cd-as-enforcement-gate
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "decision_id": "dec-001", | ||
| "verdict": "PASS", | ||
| "admissibility_score": 100, | ||
| "evidence_hash": "adb2ce6d5995be6b1e12e139825c5d309b1c6232fc256f3a2195e0c49839a042", | ||
| "signed": true | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| { | ||
| "decision_id": "dec-001", | ||
| "input_sources": [ | ||
| { | ||
| "source_id": "src-1", | ||
| "uri": "https://intelgraph.local/source/1", | ||
| "content_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", | ||
| "verified": true | ||
| } | ||
| ], | ||
| "transformation_steps": [ | ||
| { | ||
| "step_id": "step-1", | ||
| "operation": "normalize", | ||
| "input_hash": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | ||
| "output_hash": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" | ||
| } | ||
| ], | ||
| "model_used": "summit-cac-model-v1", | ||
| "confidence_score": 0.93, | ||
| "uncertainty_flag": false, | ||
| "decision_output": { | ||
| "action": "ALLOW", | ||
| "rationale": "Sources verified and evidence consistent" | ||
| }, | ||
| "reproducibility_hash": "828003e4bbc1dda644c776428735ca2ba184f89a6ebbabf573041396de874fdc" | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| { | ||
| "decision_id": "dec-fail-01", | ||
| "input_sources": [], | ||
| "transformation_steps": [ | ||
| { | ||
| "step_id": "step-1", | ||
| "operation": "normalize", | ||
| "input_hash": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | ||
| "output_hash": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" | ||
| } | ||
| ], | ||
| "model_used": "summit-cac-model-v1", | ||
| "confidence_score": 0.8, | ||
| "uncertainty_flag": false, | ||
| "decision_output": { | ||
| "action": "ALLOW" | ||
| }, | ||
| "reproducibility_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| { | ||
| "decision_id": "dec-fail-02", | ||
| "input_sources": [ | ||
| { | ||
| "source_id": "src-1", | ||
| "uri": "https://intelgraph.local/source/1", | ||
| "content_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", | ||
| "verified": true | ||
| } | ||
| ], | ||
| "transformation_steps": [ | ||
| { | ||
| "step_id": "step-1", | ||
| "operation": "normalize", | ||
| "input_hash": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | ||
| "output_hash": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" | ||
| } | ||
| ], | ||
| "model_used": "summit-cac-model-v1", | ||
| "confidence_score": 0.8, | ||
| "uncertainty_flag": false, | ||
| "decision_output": { | ||
| "action": "ALLOW", | ||
| "timestamp": "2026-03-31T00:00:00Z" | ||
| }, | ||
| "reproducibility_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| { | ||
| "decision_id": "dec-fail-03", | ||
| "input_sources": [ | ||
| { | ||
| "source_id": "src-1", | ||
| "uri": "https://intelgraph.local/source/1", | ||
| "content_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", | ||
| "verified": false | ||
| }, | ||
| { | ||
| "source_id": "src-2", | ||
| "uri": "https://intelgraph.local/source/2", | ||
| "content_hash": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", | ||
| "verified": true | ||
| } | ||
| ], | ||
| "transformation_steps": [ | ||
| { | ||
| "step_id": "step-1", | ||
| "operation": "resolve_conflict", | ||
| "input_hash": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | ||
| "output_hash": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" | ||
| } | ||
| ], | ||
| "model_used": "summit-cac-model-v1", | ||
| "confidence_score": 0.5, | ||
| "uncertainty_flag": true, | ||
| "decision_output": { | ||
| "action": "ALLOW" | ||
| }, | ||
| "reproducibility_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| # Cognitive Admissibility Criteria (CAC) Specification v0.1 | ||
|
|
||
| ## 1. Purpose | ||
|
|
||
| This specification defines the mandatory admissibility contract for any decision artifact emitted by Summit execution paths. | ||
|
|
||
| A decision artifact is admissible only when it satisfies all normative requirements in this specification and passes the CAC validator with a `PASS` verdict. | ||
|
|
||
| ## 2. Required Decision Fields | ||
|
|
||
| Each decision bundle **MUST** include the following top-level fields: | ||
|
|
||
| - `decision_id` (string, non-empty) | ||
| - `input_sources` (array, at least one entry) | ||
| - `transformation_steps` (array, at least one entry) | ||
| - `model_used` (string, non-empty) | ||
| - `confidence_score` (number between 0 and 1, inclusive) | ||
| - `uncertainty_flag` (boolean) | ||
| - `reproducibility_hash` (string, SHA-256 hex) | ||
|
|
||
| ## 3. Input Source Admissibility | ||
|
|
||
| For each `input_sources[]` entry: | ||
|
|
||
| - `source_id` **MUST** be present and non-empty. | ||
| - `uri` **MUST** be present and non-empty. | ||
| - `content_hash` **MUST** be present and must be SHA-256 hex. | ||
| - `verified` **MUST** be `true` for admissibility. | ||
| - Unverified or unverifiable sources **MUST NOT** pass CAC. | ||
|
|
||
| ## 4. Transformation Step Admissibility | ||
|
|
||
| For each `transformation_steps[]` entry: | ||
|
|
||
| - `step_id` **MUST** be present and non-empty. | ||
| - `operation` **MUST** be present and non-empty. | ||
| - `input_hash` **MUST** be SHA-256 hex. | ||
| - `output_hash` **MUST** be SHA-256 hex. | ||
|
|
||
| Transformation steps **MUST** represent a deterministic chain for identical input evidence and model configuration. | ||
|
|
||
| ## 5. Determinism Requirements | ||
|
|
||
| - Decision bundles **MUST NOT** embed runtime-dependent fields inside deterministic artifacts (for example: dynamic timestamps, random seeds, hostnames, process IDs). | ||
| - Reproducibility **MUST** be checked by recomputing `reproducibility_hash` from a canonicalized payload that excludes `reproducibility_hash` itself. | ||
| - If recomputed hash differs from supplied hash, validation **MUST** fail. | ||
|
|
||
| ## 6. Verdict Rules | ||
|
|
||
| - CAC validation **MUST** output a binary verdict: `PASS` or `FAIL`. | ||
| - Any missing required field **MUST** produce `FAIL`. | ||
| - Any determinism violation **MUST** produce `FAIL`. | ||
| - Any unverifiable source **MUST** produce `FAIL`. | ||
|
|
||
| ## 7. Certification Requirements (CACert) | ||
|
|
||
| A CACert artifact may be generated only when verdict is `PASS`. | ||
|
|
||
| CACert **MUST** include: | ||
|
|
||
| - `decision_id` | ||
| - `verdict` (`PASS`) | ||
| - `admissibility_score` | ||
| - `evidence_hash` | ||
| - `signed` (`true` only when signing succeeds) | ||
|
|
||
| Unsigned artifacts **MUST NOT** be treated as certified. |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| { | ||
| "$schema": "https://json-schema.org/draft/2020-12/schema", | ||
| "$id": "https://summit.dev/schemas/cac.schema.json", | ||
| "title": "Cognitive Admissibility Decision Bundle", | ||
| "type": "object", | ||
| "required": [ | ||
| "decision_id", | ||
| "input_sources", | ||
| "transformation_steps", | ||
| "model_used", | ||
| "confidence_score", | ||
| "uncertainty_flag", | ||
| "reproducibility_hash" | ||
| ], | ||
| "additionalProperties": false, | ||
| "properties": { | ||
| "decision_id": { "type": "string", "minLength": 1 }, | ||
| "model_used": { "type": "string", "minLength": 1 }, | ||
| "confidence_score": { "type": "number", "minimum": 0, "maximum": 1 }, | ||
| "uncertainty_flag": { "type": "boolean" }, | ||
| "reproducibility_hash": { "type": "string", "pattern": "^[a-f0-9]{64}$" }, | ||
| "input_sources": { | ||
| "type": "array", | ||
| "minItems": 1, | ||
| "items": { | ||
| "type": "object", | ||
| "required": ["source_id", "uri", "content_hash", "verified"], | ||
| "additionalProperties": false, | ||
| "properties": { | ||
| "source_id": { "type": "string", "minLength": 1 }, | ||
| "uri": { "type": "string", "minLength": 1 }, | ||
| "content_hash": { "type": "string", "pattern": "^[a-f0-9]{64}$" }, | ||
| "verified": { "type": "boolean" } | ||
| } | ||
| } | ||
| }, | ||
| "transformation_steps": { | ||
| "type": "array", | ||
| "minItems": 1, | ||
| "items": { | ||
| "type": "object", | ||
| "required": ["step_id", "operation", "input_hash", "output_hash"], | ||
| "additionalProperties": false, | ||
| "properties": { | ||
| "step_id": { "type": "string", "minLength": 1 }, | ||
| "operation": { "type": "string", "minLength": 1 }, | ||
| "input_hash": { "type": "string", "pattern": "^[a-f0-9]{64}$" }, | ||
| "output_hash": { "type": "string", "pattern": "^[a-f0-9]{64}$" } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| version: 1 | ||
| owner: governance | ||
| flow: | ||
| - stage: decision | ||
| artifact: decision-trace | ||
| path: packages/core/decision-trace.ts | ||
| - stage: artifacts | ||
| artifact: decision-bundle | ||
| path: artifacts/sample-decision-bundle.json | ||
| - stage: validation | ||
| artifact: cac-verdict | ||
| path: artifacts/cac-verdict.json | ||
| - stage: certification | ||
| artifact: cacert | ||
| path: artifacts/cacert.json | ||
| contracts: | ||
| admissibility_spec: docs/cac/CAC_SPEC_v0.1.md | ||
| schema: docs/cac/cac.schema.json | ||
| validator: packages/validators/cac-validator.ts |
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| import { createHash } from 'node:crypto'; | ||
|
|
||
| export interface CACInputSource { | ||
| source_id: string; | ||
| uri: string; | ||
| content_hash: string; | ||
| verified: boolean; | ||
| } | ||
|
|
||
| export interface CACTransformationStep { | ||
| step_id: string; | ||
| operation: string; | ||
| input_hash: string; | ||
| output_hash: string; | ||
| } | ||
|
|
||
| export interface DecisionTraceBundle { | ||
| decision_id: string; | ||
| input_sources: CACInputSource[]; | ||
| transformation_steps: CACTransformationStep[]; | ||
| model_used: string; | ||
| confidence_score: number; | ||
| uncertainty_flag: boolean; | ||
| decision_output: Record<string, unknown>; | ||
| reproducibility_hash: string; | ||
| } | ||
|
|
||
| interface DecisionTraceInput { | ||
| decision_id: string; | ||
| input_sources: CACInputSource[]; | ||
| transformation_steps: CACTransformationStep[]; | ||
| model_used: string; | ||
| confidence_score: number; | ||
| uncertainty_flag: boolean; | ||
| decision_output: Record<string, unknown>; | ||
| } | ||
|
|
||
| function stableSortObject(value: unknown): unknown { | ||
| if (Array.isArray(value)) { | ||
| return value.map(stableSortObject); | ||
| } | ||
|
|
||
| if (value && typeof value === 'object') { | ||
| return Object.keys(value as Record<string, unknown>) | ||
| .sort((a, b) => a.localeCompare(b)) | ||
| .reduce<Record<string, unknown>>((acc, key) => { | ||
| acc[key] = stableSortObject((value as Record<string, unknown>)[key]); | ||
| return acc; | ||
| }, {}); | ||
| } | ||
|
|
||
| return value; | ||
| } | ||
|
|
||
| export function canonicalize(value: unknown): string { | ||
| return JSON.stringify(stableSortObject(value)); | ||
| } | ||
|
|
||
| export function sha256Hex(value: string): string { | ||
| return createHash('sha256').update(value).digest('hex'); | ||
| } | ||
|
|
||
| export function computeReproducibilityHash( | ||
| payload: Omit<DecisionTraceBundle, 'reproducibility_hash'>, | ||
| ): string { | ||
| return sha256Hex(canonicalize(payload)); | ||
| } | ||
|
|
||
| export function emitDecisionTrace(input: DecisionTraceInput): DecisionTraceBundle { | ||
| const bundleWithoutHash: Omit<DecisionTraceBundle, 'reproducibility_hash'> = { | ||
| decision_id: input.decision_id, | ||
| input_sources: input.input_sources, | ||
| transformation_steps: input.transformation_steps, | ||
| model_used: input.model_used, | ||
| confidence_score: input.confidence_score, | ||
| uncertainty_flag: input.uncertainty_flag, | ||
| decision_output: input.decision_output, | ||
| }; | ||
|
|
||
| return { | ||
| ...bundleWithoutHash, | ||
| reproducibility_hash: computeReproducibilityHash(bundleWithoutHash), | ||
| }; | ||
| } | ||
|
|
||
| export async function withDecisionTrace<T>( | ||
| traceInput: Omit<DecisionTraceInput, 'decision_output'>, | ||
| decisionFn: () => Promise<T> | T, | ||
| ): Promise<DecisionTraceBundle> { | ||
| const decision_output = (await decisionFn()) as Record<string, unknown>; | ||
|
|
||
| return emitDecisionTrace({ | ||
| ...traceInput, | ||
| decision_output, | ||
| }); | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The schema sets
additionalProperties: falsebut does not definedecision_output, while the emitted/validated bundles include that field as required. Any consumer that validates bundles againstdocs/cac/cac.schema.jsonwill reject otherwise valid artifacts, so the machine-readable contract is internally inconsistent with the implemented validator and sample bundle format.Useful? React with 👍 / 👎.