# Evidence Hooks Reference ## Overview **Evidence Hooks** require specific attestations before an exception can be approved. This ensures exceptions are backed by verifiable proof, not just assertions. ## Hook Model ```yaml evidenceHooks: - hookId: "feature-flag-off" type: FeatureFlagDisabled description: "Feature flag must be disabled in production" isMandatory: true maxAge: PT24H # ISO 8601 duration minTrustScore: 0.8 ``` ## Hook Types ### FeatureFlagDisabled Requires attestation that a feature flag is disabled. | Field | Type | Description | |-------|------|-------------| | flagName | string | Name of the feature flag | | environment | string | Target environment | | attestedAt | timestamp | When flag state was verified | **Evidence Example:** ```json { "type": "FeatureFlagDisabled", "flagName": "EXPERIMENTAL_TEMPLATE_ENGINE", "environment": "production", "attestedAt": "2024-12-22T10:00:00Z", "source": "launchdarkly" } ``` ### BackportMerged Requires attestation that a security backport was merged. | Field | Type | Description | |-------|------|-------------| | prUrl | string | Pull request URL | | commitHash | string | Merged commit hash | | mergedAt | timestamp | When PR was merged | **Evidence Example:** ```json { "type": "BackportMerged", "prUrl": "https://github.com/org/repo/pull/123", "commitHash": "abc123...", "mergedAt": "2024-12-22T09:30:00Z", "mergedBy": "security-team" } ``` ### CompensatingControl Requires attestation of a compensating security control. | Field | Type | Description | |-------|------|-------------| | controlType | string | Type of control (WAF, RASP, etc.) | | controlId | string | Control identifier | | description | string | How control mitigates risk | **Evidence Example:** ```json { "type": "CompensatingControl", "controlType": "WAF", "controlId": "rule-block-template-injection", "description": "WAF rule blocks template injection patterns", "deployedAt": "2024-12-22T08:00:00Z" } ``` ### SecurityReview Requires attestation of completed security review. | Field | Type | Description | |-------|------|-------------| | reviewId | string | Review identifier | | reviewer | string | Who performed review | | outcome | string | Review outcome | ### RuntimeMitigation Requires attestation of runtime mitigation in place. | Field | Type | Description | |-------|------|-------------| | mitigationType | string | Type of mitigation | | configuration | object | Mitigation configuration | ### WAFRuleDeployed Requires attestation of WAF rule deployment. | Field | Type | Description | |-------|------|-------------| | ruleId | string | WAF rule identifier | | provider | string | WAF provider | | deployedAt | timestamp | Deployment time | ### CustomAttestation Generic attestation for custom evidence types. | Field | Type | Description | |-------|------|-------------| | predicateType | string | Custom predicate type URI | | payload | object | Custom payload | ## Validation Rules ### Freshness (maxAge) Evidence must be recent enough: ```yaml maxAge: PT24H # 24 hours maxAge: P7D # 7 days maxAge: PT1H # 1 hour ``` If evidence is older than maxAge, it's marked as **Expired**. ### Trust Score (minTrustScore) Evidence source must meet minimum trust: ```yaml minTrustScore: 0.8 # 80% trust required ``` Trust scores come from the source registry. ### Signature Verification If evidence includes a DSSE envelope, signature is verified: ```json { "content": { ... }, "dsseEnvelope": "eyJwYXlsb2FkIjoi...", "signatureVerified": true } ``` ### Schema Validation Custom attestations can require schema validation: ```yaml validationSchema: "https://stellaops.io/schemas/evidence/feature-flag/v1" ``` ## Validation States | State | Description | |-------|-------------| | `Pending` | Evidence submitted, not yet validated | | `Valid` | Evidence passes all validation | | `Invalid` | Evidence fails validation | | `Expired` | Evidence older than maxAge | | `InsufficientTrust` | Source trust score too low | ## Submission Flow ``` 1. User selects exception to approve 2. System shows required evidence hooks 3. User submits evidence for each hook: a. Upload attestation file b. Link to external system c. Generate attestation in-place 4. System validates each submission 5. If all mandatory hooks satisfied: a. Exception can be approved 6. If any mandatory hooks unsatisfied: a. Approval blocked b. Missing evidence highlighted ``` ## API Endpoints ### POST /exceptions/{id}/evidence Submit evidence for a hook. **Request:** ```json { "hookId": "feature-flag-off", "type": "FeatureFlagDisabled", "reference": "launchdarkly://flags/EXPERIMENTAL_TEMPLATE_ENGINE", "content": { "flagName": "EXPERIMENTAL_TEMPLATE_ENGINE", "environment": "production", "state": "off" } } ``` ### GET /exceptions/{id}/evidence Get all submitted evidence for an exception. ### GET /exceptions/{id}/evidence/status Get evidence satisfaction status. **Response:** ```json { "isSatisfied": false, "missingEvidence": [ { "hookId": "backport-merged", "type": "BackportMerged", "description": "Security backport must be merged" } ], "validEvidence": [ { "hookId": "feature-flag-off", "type": "FeatureFlagDisabled", "validatedAt": "2024-12-22T10:00:00Z" } ] } ``` ## UI Integration ### Evidence Requirements Panel Shows required evidence with status: ``` Evidence Requirements --------------------- [x] Feature flag disabled (Verified 2h ago) [ ] Backport PR merged (Missing) [x] WAF rule deployed (Verified 1d ago) [Submit Missing Evidence] ``` ### Evidence Upload Modal For each hook type: 1. File upload for attestations 2. URL input for external references 3. Form for in-place attestation ### Blocking Indicator When evidence is missing: - Approve button disabled - Clear message: "Cannot approve: missing evidence" - Link to evidence requirements ## Best Practices 1. **Mandatory = Critical**: Only mark truly required evidence as mandatory 2. **Reasonable maxAge**: Balance freshness with operational burden 3. **Trust Scores**: Configure source trust appropriately 4. **Documentation**: Document what each evidence type means 5. **Automation**: Integrate with systems to auto-generate attestations ## DSSE Attestation Format Evidence can be wrapped in DSSE for integrity: ```json { "payloadType": "application/vnd.stellaops.evidence+json", "payload": "", "signatures": [ { "keyid": "key-123", "sig": "" } ] } ``` ## Example Hook Configurations ### Critical CVE Policy ```yaml evidenceHooks: - hookId: "security-review" type: SecurityReview description: "Security team review required" isMandatory: true - hookId: "compensating-control" type: CompensatingControl description: "Compensating control must be in place" isMandatory: true - hookId: "stakeholder-approval" type: CustomAttestation description: "Business stakeholder approval" isMandatory: true validationSchema: "https://stellaops.io/schemas/evidence/stakeholder-approval/v1" ``` ### Standard Policy ```yaml evidenceHooks: - hookId: "justification" type: CustomAttestation description: "Written justification required" isMandatory: true - hookId: "compensating-control" type: CompensatingControl description: "Compensating control recommended" isMandatory: false ``` ## Related Documentation - [Recheck Policy](./recheck-policy.md) - [Exception Workflow](../../api/exceptions.md) - [DSSE Attestations](../attestor/dsse.md)