diff --git a/.github/policies/osint/alert_budget.rego b/.github/policies/osint/alert_budget.rego new file mode 100644 index 00000000000..04d8b6ec3bc --- /dev/null +++ b/.github/policies/osint/alert_budget.rego @@ -0,0 +1,16 @@ +package osint.alert_budget + +default allow = false + +deny["unknown_envelope"] if { + not input.risk_envelopes[input.risk_envelope] +} + +deny["alert_budget_exceeded"] if { + envelope := input.risk_envelopes[input.risk_envelope] + input.collection.alert_count > envelope.max_alerts_per_run +} + +allow if { + count(deny) == 0 +} diff --git a/.github/policies/osint/alert_budget_test.rego b/.github/policies/osint/alert_budget_test.rego new file mode 100644 index 00000000000..284d495cf42 --- /dev/null +++ b/.github/policies/osint/alert_budget_test.rego @@ -0,0 +1,15 @@ +package osint.alert_budget_test + +test_deny_alert_budget_exceeded if { + denies := data.osint.alert_budget.deny with input as data.osint.fixtures.alert_deny_exceeded + count(denies) > 0 +} + +test_deny_unknown_envelope if { + denies := data.osint.alert_budget.deny with input as data.osint.fixtures.alert_deny_unknown_envelope + count(denies) > 0 +} + +test_allow_alert_budget_valid if { + data.osint.alert_budget.allow with input as data.osint.fixtures.alert_allow_valid +} diff --git a/.github/policies/osint/fixtures/alert_allow_valid.json b/.github/policies/osint/fixtures/alert_allow_valid.json new file mode 100644 index 00000000000..6548fa5b4f0 --- /dev/null +++ b/.github/policies/osint/fixtures/alert_allow_valid.json @@ -0,0 +1,11 @@ +{ + "risk_envelope": "balanced", + "risk_envelopes": { + "balanced": { + "max_alerts_per_run": 75 + } + }, + "collection": { + "alert_count": 50 + } +} diff --git a/.github/policies/osint/fixtures/alert_deny_exceeded.json b/.github/policies/osint/fixtures/alert_deny_exceeded.json new file mode 100644 index 00000000000..51d4e0b5e9a --- /dev/null +++ b/.github/policies/osint/fixtures/alert_deny_exceeded.json @@ -0,0 +1,11 @@ +{ + "risk_envelope": "conservative", + "risk_envelopes": { + "conservative": { + "max_alerts_per_run": 25 + } + }, + "collection": { + "alert_count": 30 + } +} diff --git a/.github/policies/osint/fixtures/alert_deny_unknown_envelope.json b/.github/policies/osint/fixtures/alert_deny_unknown_envelope.json new file mode 100644 index 00000000000..c083394fb13 --- /dev/null +++ b/.github/policies/osint/fixtures/alert_deny_unknown_envelope.json @@ -0,0 +1,11 @@ +{ + "risk_envelope": "unsupported", + "risk_envelopes": { + "conservative": { + "max_alerts_per_run": 25 + } + }, + "collection": { + "alert_count": 1 + } +} diff --git a/.github/policies/osint/fixtures/privacy_allow_valid.json b/.github/policies/osint/fixtures/privacy_allow_valid.json new file mode 100644 index 00000000000..520cdd2aca6 --- /dev/null +++ b/.github/policies/osint/fixtures/privacy_allow_valid.json @@ -0,0 +1,9 @@ +{ + "collection": { + "pii_fields": ["email"], + "redactions": ["email"], + "retention_ttl_days": 7, + "never_log_fields": ["tokens"], + "logged_fields": ["title"] + } +} diff --git a/.github/policies/osint/fixtures/privacy_deny_pii.json b/.github/policies/osint/fixtures/privacy_deny_pii.json new file mode 100644 index 00000000000..558a1a7df36 --- /dev/null +++ b/.github/policies/osint/fixtures/privacy_deny_pii.json @@ -0,0 +1,9 @@ +{ + "collection": { + "pii_fields": ["email"], + "redactions": [], + "retention_ttl_days": 7, + "never_log_fields": ["tokens"], + "logged_fields": ["title"] + } +} diff --git a/.github/policies/osint/fixtures/privacy_deny_retention.json b/.github/policies/osint/fixtures/privacy_deny_retention.json new file mode 100644 index 00000000000..a89bfed2bee --- /dev/null +++ b/.github/policies/osint/fixtures/privacy_deny_retention.json @@ -0,0 +1,9 @@ +{ + "collection": { + "pii_fields": [], + "redactions": [], + "retention_ttl_days": 0, + "never_log_fields": ["tokens"], + "logged_fields": ["title"] + } +} diff --git a/.github/policies/osint/fixtures/provenance_allow_valid.json b/.github/policies/osint/fixtures/provenance_allow_valid.json new file mode 100644 index 00000000000..bd1bf1b2ba1 --- /dev/null +++ b/.github/policies/osint/fixtures/provenance_allow_valid.json @@ -0,0 +1,10 @@ +{ + "collection": { + "provenance": { + "artifact_ids": ["A1", "A2"], + "corroboration_count": 2, + "single_source": false, + "escalation": true + } + } +} diff --git a/.github/policies/osint/fixtures/provenance_deny_escalation.json b/.github/policies/osint/fixtures/provenance_deny_escalation.json new file mode 100644 index 00000000000..779fd4a11d3 --- /dev/null +++ b/.github/policies/osint/fixtures/provenance_deny_escalation.json @@ -0,0 +1,10 @@ +{ + "collection": { + "provenance": { + "artifact_ids": ["A1"], + "corroboration_count": 1, + "single_source": true, + "escalation": true + } + } +} diff --git a/.github/policies/osint/fixtures/provenance_deny_missing_artifacts.json b/.github/policies/osint/fixtures/provenance_deny_missing_artifacts.json new file mode 100644 index 00000000000..9ae36cc0007 --- /dev/null +++ b/.github/policies/osint/fixtures/provenance_deny_missing_artifacts.json @@ -0,0 +1,10 @@ +{ + "collection": { + "provenance": { + "artifact_ids": [], + "corroboration_count": 0, + "single_source": true, + "escalation": false + } + } +} diff --git a/.github/policies/osint/fixtures/tos_allow_valid.json b/.github/policies/osint/fixtures/tos_allow_valid.json new file mode 100644 index 00000000000..45750e39f56 --- /dev/null +++ b/.github/policies/osint/fixtures/tos_allow_valid.json @@ -0,0 +1,18 @@ +{ + "collection": { + "source_id": "summit-news-api", + "method": "api" + }, + "risk_envelope": "conservative", + "risk_envelopes": { + "conservative": { + "allowed_methods": ["api"] + } + }, + "source_registry": { + "summit-news-api": { + "allowed_methods": ["api"], + "disallowed_methods": ["paywall_bypass"] + } + } +} diff --git a/.github/policies/osint/fixtures/tos_deny_method.json b/.github/policies/osint/fixtures/tos_deny_method.json new file mode 100644 index 00000000000..7cc616fb596 --- /dev/null +++ b/.github/policies/osint/fixtures/tos_deny_method.json @@ -0,0 +1,18 @@ +{ + "collection": { + "source_id": "summit-news-api", + "method": "web_fetch" + }, + "risk_envelope": "conservative", + "risk_envelopes": { + "conservative": { + "allowed_methods": ["api"] + } + }, + "source_registry": { + "summit-news-api": { + "allowed_methods": ["api"], + "disallowed_methods": ["paywall_bypass"] + } + } +} diff --git a/.github/policies/osint/fixtures/tos_deny_unregistered.json b/.github/policies/osint/fixtures/tos_deny_unregistered.json new file mode 100644 index 00000000000..3b93d0ca272 --- /dev/null +++ b/.github/policies/osint/fixtures/tos_deny_unregistered.json @@ -0,0 +1,13 @@ +{ + "collection": { + "source_id": "unknown-source", + "method": "api" + }, + "risk_envelope": "conservative", + "risk_envelopes": { + "conservative": { + "allowed_methods": ["api"] + } + }, + "source_registry": {} +} diff --git a/.github/policies/osint/privacy.rego b/.github/policies/osint/privacy.rego new file mode 100644 index 00000000000..b7a80c7040e --- /dev/null +++ b/.github/policies/osint/privacy.rego @@ -0,0 +1,30 @@ +package osint.privacy + +default allow = false + +deny["pii_not_redacted"] if { + pii := input.collection.pii_fields[_] + not redacted(pii) +} + +deny["retention_ttl_missing"] if { + not input.collection.retention_ttl_days +} + +deny["retention_ttl_missing"] if { + input.collection.retention_ttl_days <= 0 +} + +deny["never_log_field_present"] if { + never_log := input.collection.never_log_fields[_] + logged := input.collection.logged_fields[_] + never_log == logged +} + +allow if { + count(deny) == 0 +} + +redacted(field) { + input.collection.redactions[_] == field +} diff --git a/.github/policies/osint/privacy_test.rego b/.github/policies/osint/privacy_test.rego new file mode 100644 index 00000000000..43e25b90c85 --- /dev/null +++ b/.github/policies/osint/privacy_test.rego @@ -0,0 +1,15 @@ +package osint.privacy_test + +test_deny_missing_redaction if { + denies := data.osint.privacy.deny with input as data.osint.fixtures.privacy_deny_pii + count(denies) > 0 +} + +test_deny_invalid_retention if { + denies := data.osint.privacy.deny with input as data.osint.fixtures.privacy_deny_retention + count(denies) > 0 +} + +test_allow_valid_redaction if { + data.osint.privacy.allow with input as data.osint.fixtures.privacy_allow_valid +} diff --git a/.github/policies/osint/provenance.rego b/.github/policies/osint/provenance.rego new file mode 100644 index 00000000000..025b6272e68 --- /dev/null +++ b/.github/policies/osint/provenance.rego @@ -0,0 +1,21 @@ +package osint.provenance + +default allow = false + +deny["missing_artifacts"] if { + count(input.collection.provenance.artifact_ids) == 0 +} + +deny["escalation_single_source"] if { + input.collection.provenance.escalation + input.collection.provenance.single_source +} + +deny["insufficient_corroboration"] if { + input.collection.provenance.escalation + input.collection.provenance.corroboration_count < 2 +} + +allow if { + count(deny) == 0 +} diff --git a/.github/policies/osint/provenance_test.rego b/.github/policies/osint/provenance_test.rego new file mode 100644 index 00000000000..125e9ea3824 --- /dev/null +++ b/.github/policies/osint/provenance_test.rego @@ -0,0 +1,15 @@ +package osint.provenance_test + +test_deny_missing_artifacts if { + denies := data.osint.provenance.deny with input as data.osint.fixtures.provenance_deny_missing_artifacts + count(denies) > 0 +} + +test_deny_escalation_single_source if { + denies := data.osint.provenance.deny with input as data.osint.fixtures.provenance_deny_escalation + count(denies) > 0 +} + +test_allow_valid_provenance if { + data.osint.provenance.allow with input as data.osint.fixtures.provenance_allow_valid +} diff --git a/.github/policies/osint/tos.rego b/.github/policies/osint/tos.rego new file mode 100644 index 00000000000..0d4d0748c3c --- /dev/null +++ b/.github/policies/osint/tos.rego @@ -0,0 +1,49 @@ +package osint.tos + +default allow = false + +deny["source_not_registered"] if { + not input.source_registry[input.collection.source_id] +} + +deny["envelope_missing"] if { + not input.risk_envelopes[input.risk_envelope] +} + +deny["method_not_allowed"] if { + source := input.source_registry[input.collection.source_id] + method := input.collection.method + not method_allowed(source.allowed_methods, method) +} + +deny["method_not_allowed_by_envelope"] if { + envelope := input.risk_envelopes[input.risk_envelope] + method := input.collection.method + not method_allowed(envelope.allowed_methods, method) +} + +deny["method_explicitly_disallowed"] if { + source := input.source_registry[input.collection.source_id] + method := input.collection.method + method_allowed(source.disallowed_methods, method) +} + +deny["disallowed_tos_method"] if { + input.collection.method == "circumvent" +} + +deny["disallowed_tos_method"] if { + input.collection.method == "credential_share" +} + +deny["disallowed_tos_method"] if { + input.collection.method == "paywall_bypass" +} + +allow if { + count(deny) == 0 +} + +method_allowed(methods, method) { + methods[_] == method +} diff --git a/.github/policies/osint/tos_test.rego b/.github/policies/osint/tos_test.rego new file mode 100644 index 00000000000..575d6ff8bde --- /dev/null +++ b/.github/policies/osint/tos_test.rego @@ -0,0 +1,15 @@ +package osint.tos_test + +test_deny_unregistered_source if { + denies := data.osint.tos.deny with input as data.osint.fixtures.tos_deny_unregistered + count(denies) > 0 +} + +test_deny_disallowed_method if { + denies := data.osint.tos.deny with input as data.osint.fixtures.tos_deny_method + count(denies) > 0 +} + +test_allow_valid_source if { + data.osint.tos.allow with input as data.osint.fixtures.tos_allow_valid +} diff --git a/.github/workflows/osint-governance-verify.yml b/.github/workflows/osint-governance-verify.yml new file mode 100644 index 00000000000..7a9d2172255 --- /dev/null +++ b/.github/workflows/osint-governance-verify.yml @@ -0,0 +1,38 @@ +name: osint-governance-verify + +on: + pull_request: + paths: + - 'config/osint/**' + - 'schemas/osint/**' + - '.github/policies/osint/**' + - 'evidence/**' + - '.github/workflows/osint-governance-verify.yml' + workflow_dispatch: + +jobs: + osint-governance-verify: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup OPA + uses: open-policy-agent/setup-opa@v2 + with: + version: latest + + - name: Run OSINT policy tests + run: opa test .github/policies/osint + + - name: Schema presence checks + run: | + set -euo pipefail + test -s config/osint/sources.yml + test -s config/osint/risk_envelopes.yml + test -s config/osint/retention.yml + test -s schemas/osint/source_registry.schema.json + test -s schemas/osint/risk_envelopes.schema.json + test -s schemas/osint/provenance_receipt.schema.json + test -s schemas/osint/collection_event.schema.json + test -s schemas/osint/redaction_report.schema.json diff --git a/agents/examples/OSINT_LIMITS_ENVELOPE_PR1.json b/agents/examples/OSINT_LIMITS_ENVELOPE_PR1.json new file mode 100644 index 00000000000..8e672b7e35b --- /dev/null +++ b/agents/examples/OSINT_LIMITS_ENVELOPE_PR1.json @@ -0,0 +1,46 @@ +{ + "task_id": "OSINT_LIMITS_ENVELOPE_PR1", + "agent_id": "codex", + "prompt_ref": { + "id": "osint-guardrails-pr1", + "version": "v1", + "sha256": "c49c6265b215927aa7a3b78e1471e62638e62fcfbf9037d19aa25a5b74c01c74", + "path": "prompts/governance/osint-guardrails-pr1@v1.md" + }, + "declared_scope": { + "paths": [ + "config/osint/", + "schemas/osint/", + ".github/policies/osint/", + ".github/workflows/osint-governance-verify.yml", + "evidence/index.json", + "evidence/EVD-OSINT-LIMITS-ENVELOPE-*/", + "docs/roadmap/STATUS.json", + "agents/examples/OSINT_LIMITS_ENVELOPE_PR1.json" + ], + "domains": ["governance", "policy", "evidence", "ci"] + }, + "allowed_operations": ["create", "edit"], + "verification_requirements": { + "tier": "C", + "artifacts": [ + "opa-test-output", + "schema-presence-checks", + "evidence-index-entry" + ] + }, + "debt_budget": { + "permitted": 0, + "retirement_target": 0 + }, + "success_criteria": [ + "OSINT configs, schemas, and policy gates are added with deny-by-default fixtures.", + "CI workflow validates OPA tests and schema presence.", + "Evidence index includes OSINT limit envelope entries." + ], + "stop_conditions": [ + "Policy fixtures fail in CI.", + "Schema presence checks fail.", + "Evidence index missing required OSINT entries." + ] +} diff --git a/config/osint/retention.yml b/config/osint/retention.yml new file mode 100644 index 00000000000..0a80dfdc6e6 --- /dev/null +++ b/config/osint/retention.yml @@ -0,0 +1,33 @@ +version: 1 +classification: + public: + raw_capture_ttl_days: 14 + metadata_ttl_days: 365 + internal: + raw_capture_ttl_days: 7 + metadata_ttl_days: 365 + restricted: + raw_capture_ttl_days: 3 + metadata_ttl_days: 180 + sensitive_personal: + raw_capture_ttl_days: 1 + metadata_ttl_days: 90 +never_log_fields: + - tokens + - session_cookies + - full_html + - personal_identifiers + - raw_credentials +redaction: + pii_fields: + - email + - phone + - ssn + - passport_number + - national_id + strategy: "mask" +retention_overrides: + - source_id: summit-open-web + classification: restricted + raw_capture_ttl_days: 1 + metadata_ttl_days: 90 diff --git a/config/osint/risk_envelopes.yml b/config/osint/risk_envelopes.yml new file mode 100644 index 00000000000..8360115a60c --- /dev/null +++ b/config/osint/risk_envelopes.yml @@ -0,0 +1,32 @@ +version: 1 +envelopes: + conservative: + description: "Documented APIs only with explicit automation permission." + allowed_methods: + - api + allow_authenticated_access: false + allow_headless_browsing: false + max_alerts_per_run: 25 + min_corroboration: 2 + require_human_review_on_escalation: true + balanced: + description: "APIs plus RSS/robots-allowed fetch with stricter privacy controls." + allowed_methods: + - api + - rss + allow_authenticated_access: true + allow_headless_browsing: false + max_alerts_per_run: 75 + min_corroboration: 2 + require_human_review_on_escalation: true + max_legal: + description: "Broader allowed methods where ToS permits, with mandatory escalation review." + allowed_methods: + - api + - rss + - web_fetch + allow_authenticated_access: true + allow_headless_browsing: true + max_alerts_per_run: 150 + min_corroboration: 2 + require_human_review_on_escalation: true diff --git a/config/osint/sources.yml b/config/osint/sources.yml new file mode 100644 index 00000000000..ffe76d9bbed --- /dev/null +++ b/config/osint/sources.yml @@ -0,0 +1,63 @@ +version: 1 +default_risk_envelope: conservative +source_tiers: + tier_1_high: + description: "High-reliability sources with explicit automation terms and stable APIs." + tier_2_medium: + description: "Moderate-reliability sources with published access terms and verified provenance." + tier_3_low: + description: "Low-reliability sources requiring corroboration and human review before escalation." +source_onboarding_checklist: + - Confirm ToS explicitly allows automation or licensed API access. + - Record approved collection methods and disallowed methods. + - Capture rate limits, quotas, and backoff requirements. + - Document licensing and redistribution constraints. + - Validate provenance expectations and required metadata fields. + - Assign reliability tier and review cadence. + - Register privacy classification and retention TTLs. + - Add negative-policy fixtures for new source rules. + - Obtain human review sign-off for scope or rate-limit changes. +sources: + - id: summit-news-api + name: "Summit News API" + tos_class: "allows_automation" + allowed_methods: + - api + disallowed_methods: + - circumvent + - credential_share + - paywall_bypass + reliability_tier: tier_1_high + license: "commercial" + rate_limit_per_min: 60 + geo_restrictions: [] + notes: "Primary API source for news metadata." + - id: summit-rss-wire + name: "Summit RSS Wire" + tos_class: "robots_allowed" + allowed_methods: + - rss + disallowed_methods: + - headless_browser + - paywall_bypass + reliability_tier: tier_2_medium + license: "attribution_required" + rate_limit_per_min: 30 + geo_restrictions: + - "EU" + notes: "RSS feed with robots-allowed access only." + - id: summit-open-web + name: "Summit Open Web" + tos_class: "manual_review_required" + allowed_methods: + - api + - rss + disallowed_methods: + - headless_browser + - paywall_bypass + - circumvent + reliability_tier: tier_3_low + license: "unknown" + rate_limit_per_min: 10 + geo_restrictions: [] + notes: "Low-reliability public sources requiring corroboration." diff --git a/docs/roadmap/STATUS.json b/docs/roadmap/STATUS.json index 281d973af71..9773f6b1bf9 100644 --- a/docs/roadmap/STATUS.json +++ b/docs/roadmap/STATUS.json @@ -1,6 +1,6 @@ { "last_updated": "2026-02-07T00:00:00Z", - "revision_note": "Added Summit PR Stack Sequencer skill scaffolding.", + "revision_note": "Added OSINT limits envelope lane-1 scaffolding initiative.", "initiatives": [ { "id": "adenhq-hive-subsumption-lane1", @@ -193,6 +193,12 @@ "status": "in_progress", "owner": "codex", "notes": "Documented CI/CD high-signal deltas with enforced action register and evidence targets." + }, + { + "id": "osint-limits-envelope-lane1", + "status": "in_progress", + "owner": "codex", + "notes": "OSINT guardrails lane-1: source registry, risk envelopes, policy gates, fixtures, evidence scaffolding, and CI verifier." } ], "summary": { @@ -200,7 +206,7 @@ "partial": 2, "incomplete": 0, "not_started": 5, - "total": 17, + "total": 18, "ga_blockers": [] } } diff --git a/evidence/EVD-OSINT-LIMITS-ENVELOPE-POLICY-001/metrics.json b/evidence/EVD-OSINT-LIMITS-ENVELOPE-POLICY-001/metrics.json new file mode 100644 index 00000000000..b3736ef36b3 --- /dev/null +++ b/evidence/EVD-OSINT-LIMITS-ENVELOPE-POLICY-001/metrics.json @@ -0,0 +1,5 @@ +{ + "policies": 4, + "fixtures": 12, + "status": "scaffolded" +} diff --git a/evidence/EVD-OSINT-LIMITS-ENVELOPE-POLICY-001/report.json b/evidence/EVD-OSINT-LIMITS-ENVELOPE-POLICY-001/report.json new file mode 100644 index 00000000000..274976ec108 --- /dev/null +++ b/evidence/EVD-OSINT-LIMITS-ENVELOPE-POLICY-001/report.json @@ -0,0 +1,13 @@ +{ + "evidence_id": "EVD-OSINT-LIMITS-ENVELOPE-POLICY-001", + "title": "OSINT policy gate scaffolding", + "summary": "Deny-by-default OSINT policy gates and fixtures committed for ToS, privacy, provenance, and alert budget enforcement.", + "status": "scaffolded", + "artifacts": [ + ".github/policies/osint/tos.rego", + ".github/policies/osint/privacy.rego", + ".github/policies/osint/provenance.rego", + ".github/policies/osint/alert_budget.rego" + ], + "generated_by": "osint-governance-verify" +} diff --git a/evidence/EVD-OSINT-LIMITS-ENVELOPE-POLICY-001/stamp.json b/evidence/EVD-OSINT-LIMITS-ENVELOPE-POLICY-001/stamp.json new file mode 100644 index 00000000000..ef8362b6fc0 --- /dev/null +++ b/evidence/EVD-OSINT-LIMITS-ENVELOPE-POLICY-001/stamp.json @@ -0,0 +1,3 @@ +{ + "generated_at": "2026-02-07T00:00:00Z" +} diff --git a/evidence/EVD-OSINT-LIMITS-ENVELOPE-PRIVACY-001/metrics.json b/evidence/EVD-OSINT-LIMITS-ENVELOPE-PRIVACY-001/metrics.json new file mode 100644 index 00000000000..8a3e4458cda --- /dev/null +++ b/evidence/EVD-OSINT-LIMITS-ENVELOPE-PRIVACY-001/metrics.json @@ -0,0 +1,5 @@ +{ + "classification_tiers": 4, + "never_log_fields": 5, + "status": "scaffolded" +} diff --git a/evidence/EVD-OSINT-LIMITS-ENVELOPE-PRIVACY-001/report.json b/evidence/EVD-OSINT-LIMITS-ENVELOPE-PRIVACY-001/report.json new file mode 100644 index 00000000000..6e528d84329 --- /dev/null +++ b/evidence/EVD-OSINT-LIMITS-ENVELOPE-PRIVACY-001/report.json @@ -0,0 +1,11 @@ +{ + "evidence_id": "EVD-OSINT-LIMITS-ENVELOPE-PRIVACY-001", + "title": "OSINT privacy and retention scaffolding", + "summary": "Retention defaults, never-log fields, and redaction policies defined with schema scaffolding.", + "status": "scaffolded", + "artifacts": [ + "config/osint/retention.yml", + "schemas/osint/redaction_report.schema.json" + ], + "generated_by": "osint-governance-verify" +} diff --git a/evidence/EVD-OSINT-LIMITS-ENVELOPE-PRIVACY-001/stamp.json b/evidence/EVD-OSINT-LIMITS-ENVELOPE-PRIVACY-001/stamp.json new file mode 100644 index 00000000000..ef8362b6fc0 --- /dev/null +++ b/evidence/EVD-OSINT-LIMITS-ENVELOPE-PRIVACY-001/stamp.json @@ -0,0 +1,3 @@ +{ + "generated_at": "2026-02-07T00:00:00Z" +} diff --git a/evidence/EVD-OSINT-LIMITS-ENVELOPE-PROV-001/metrics.json b/evidence/EVD-OSINT-LIMITS-ENVELOPE-PROV-001/metrics.json new file mode 100644 index 00000000000..10c64c4b6fd --- /dev/null +++ b/evidence/EVD-OSINT-LIMITS-ENVELOPE-PROV-001/metrics.json @@ -0,0 +1,4 @@ +{ + "schemas": 2, + "status": "scaffolded" +} diff --git a/evidence/EVD-OSINT-LIMITS-ENVELOPE-PROV-001/report.json b/evidence/EVD-OSINT-LIMITS-ENVELOPE-PROV-001/report.json new file mode 100644 index 00000000000..38766f295fc --- /dev/null +++ b/evidence/EVD-OSINT-LIMITS-ENVELOPE-PROV-001/report.json @@ -0,0 +1,11 @@ +{ + "evidence_id": "EVD-OSINT-LIMITS-ENVELOPE-PROV-001", + "title": "OSINT provenance receipt scaffolding", + "summary": "Provenance and collection event schemas added to enforce traceability requirements.", + "status": "scaffolded", + "artifacts": [ + "schemas/osint/provenance_receipt.schema.json", + "schemas/osint/collection_event.schema.json" + ], + "generated_by": "osint-governance-verify" +} diff --git a/evidence/EVD-OSINT-LIMITS-ENVELOPE-PROV-001/stamp.json b/evidence/EVD-OSINT-LIMITS-ENVELOPE-PROV-001/stamp.json new file mode 100644 index 00000000000..ef8362b6fc0 --- /dev/null +++ b/evidence/EVD-OSINT-LIMITS-ENVELOPE-PROV-001/stamp.json @@ -0,0 +1,3 @@ +{ + "generated_at": "2026-02-07T00:00:00Z" +} diff --git a/evidence/EVD-OSINT-LIMITS-ENVELOPE-SOURCES-001/metrics.json b/evidence/EVD-OSINT-LIMITS-ENVELOPE-SOURCES-001/metrics.json new file mode 100644 index 00000000000..83ebf562edc --- /dev/null +++ b/evidence/EVD-OSINT-LIMITS-ENVELOPE-SOURCES-001/metrics.json @@ -0,0 +1,5 @@ +{ + "sources": 3, + "tiers": 3, + "status": "scaffolded" +} diff --git a/evidence/EVD-OSINT-LIMITS-ENVELOPE-SOURCES-001/report.json b/evidence/EVD-OSINT-LIMITS-ENVELOPE-SOURCES-001/report.json new file mode 100644 index 00000000000..8d307b660dd --- /dev/null +++ b/evidence/EVD-OSINT-LIMITS-ENVELOPE-SOURCES-001/report.json @@ -0,0 +1,11 @@ +{ + "evidence_id": "EVD-OSINT-LIMITS-ENVELOPE-SOURCES-001", + "title": "OSINT source registry scaffolding", + "summary": "Source registry defaults with onboarding checklist and reliability tiers committed.", + "status": "scaffolded", + "artifacts": [ + "config/osint/sources.yml", + "schemas/osint/source_registry.schema.json" + ], + "generated_by": "osint-governance-verify" +} diff --git a/evidence/EVD-OSINT-LIMITS-ENVELOPE-SOURCES-001/stamp.json b/evidence/EVD-OSINT-LIMITS-ENVELOPE-SOURCES-001/stamp.json new file mode 100644 index 00000000000..ef8362b6fc0 --- /dev/null +++ b/evidence/EVD-OSINT-LIMITS-ENVELOPE-SOURCES-001/stamp.json @@ -0,0 +1,3 @@ +{ + "generated_at": "2026-02-07T00:00:00Z" +} diff --git a/evidence/index.json b/evidence/index.json index 4b113aa9959..a46dd24cb12 100644 --- a/evidence/index.json +++ b/evidence/index.json @@ -400,6 +400,38 @@ "metrics": "evidence/EVD-INTSUM-2026-THREAT-HORIZON-001/metrics.json", "stamp": "evidence/EVD-INTSUM-2026-THREAT-HORIZON-001/stamp.json" } + }, + { + "evidence_id": "EVD-OSINT-LIMITS-ENVELOPE-POLICY-001", + "files": { + "report": "evidence/EVD-OSINT-LIMITS-ENVELOPE-POLICY-001/report.json", + "metrics": "evidence/EVD-OSINT-LIMITS-ENVELOPE-POLICY-001/metrics.json", + "stamp": "evidence/EVD-OSINT-LIMITS-ENVELOPE-POLICY-001/stamp.json" + } + }, + { + "evidence_id": "EVD-OSINT-LIMITS-ENVELOPE-SOURCES-001", + "files": { + "report": "evidence/EVD-OSINT-LIMITS-ENVELOPE-SOURCES-001/report.json", + "metrics": "evidence/EVD-OSINT-LIMITS-ENVELOPE-SOURCES-001/metrics.json", + "stamp": "evidence/EVD-OSINT-LIMITS-ENVELOPE-SOURCES-001/stamp.json" + } + }, + { + "evidence_id": "EVD-OSINT-LIMITS-ENVELOPE-PRIVACY-001", + "files": { + "report": "evidence/EVD-OSINT-LIMITS-ENVELOPE-PRIVACY-001/report.json", + "metrics": "evidence/EVD-OSINT-LIMITS-ENVELOPE-PRIVACY-001/metrics.json", + "stamp": "evidence/EVD-OSINT-LIMITS-ENVELOPE-PRIVACY-001/stamp.json" + } + }, + { + "evidence_id": "EVD-OSINT-LIMITS-ENVELOPE-PROV-001", + "files": { + "report": "evidence/EVD-OSINT-LIMITS-ENVELOPE-PROV-001/report.json", + "metrics": "evidence/EVD-OSINT-LIMITS-ENVELOPE-PROV-001/metrics.json", + "stamp": "evidence/EVD-OSINT-LIMITS-ENVELOPE-PROV-001/stamp.json" + } } ] -} \ No newline at end of file +} diff --git a/prompts/governance/osint-guardrails-pr1@v1.md b/prompts/governance/osint-guardrails-pr1@v1.md new file mode 100644 index 00000000000..9800755a6fb --- /dev/null +++ b/prompts/governance/osint-guardrails-pr1@v1.md @@ -0,0 +1,18 @@ +# Prompt: OSINT Guardrails PR1 + +You are implementing the OSINT guardrails foundation (lane 1) in Summit. Deliverables: + +- Source registry, risk envelopes, and retention configs under `config/osint/`. +- JSON schemas for OSINT source registry, risk envelopes, provenance receipt, collection event, and redaction report under `schemas/osint/`. +- Deny-by-default OPA policies and fixtures under `.github/policies/osint/` with unit tests. +- CI workflow to validate OPA policies and schema presence under `.github/workflows/`. +- Evidence bundle scaffolding and updates to `evidence/index.json`. +- Update `docs/roadmap/STATUS.json` with the OSINT limits envelope initiative. +- Add an agent task spec under `agents/examples/` for this change. + +Constraints: + +- Deny-by-default behavior is required. +- Include two negative fixtures and one positive fixture per policy. +- Ensure deterministic evidence outputs with timestamps only in `stamp.json`. +- Follow conventional commits and repository governance rules. diff --git a/prompts/registry.yaml b/prompts/registry.yaml index 4993c520476..230afd0197a 100644 --- a/prompts/registry.yaml +++ b/prompts/registry.yaml @@ -896,3 +896,34 @@ prompts: retirement_target: 0 allowed_operations: - edit + - id: osint-guardrails-pr1 + version: v1 + path: prompts/governance/osint-guardrails-pr1@v1.md + sha256: c49c6265b215927aa7a3b78e1471e62638e62fcfbf9037d19aa25a5b74c01c74 + description: Scaffold OSINT guardrails configs, schemas, policies, fixtures, evidence, and CI verification. + scope: + paths: + - config/osint/ + - schemas/osint/ + - .github/policies/osint/ + - .github/workflows/osint-governance-verify.yml + - evidence/index.json + - evidence/EVD-OSINT-LIMITS-ENVELOPE-*/ + - docs/roadmap/STATUS.json + - agents/examples/OSINT_LIMITS_ENVELOPE_PR1.json + - prompts/governance/osint-guardrails-pr1@v1.md + - prompts/registry.yaml + domains: + - governance + - policy + - evidence + - ci + verification: + tiers_required: + - C + debt_budget: + permitted: 0 + retirement_target: 0 + allowed_operations: + - create + - edit diff --git a/schemas/osint/collection_event.schema.json b/schemas/osint/collection_event.schema.json new file mode 100644 index 00000000000..ea7bebf82c2 --- /dev/null +++ b/schemas/osint/collection_event.schema.json @@ -0,0 +1,47 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://summit.example.com/schemas/osint/collection_event.schema.json", + "title": "OSINT Collection Event", + "type": "object", + "required": [ + "event_id", + "source_id", + "method", + "risk_envelope", + "collected_at", + "retention_ttl_days", + "provenance" + ], + "additionalProperties": false, + "properties": { + "event_id": { "type": "string" }, + "source_id": { "type": "string" }, + "method": { "type": "string" }, + "risk_envelope": { "type": "string" }, + "collected_at": { "type": "string", "format": "date-time" }, + "pii_fields": { + "type": "array", + "items": { "type": "string" } + }, + "redactions": { + "type": "array", + "items": { "type": "string" } + }, + "retention_ttl_days": { "type": "integer", "minimum": 1 }, + "provenance": { + "type": "object", + "required": ["artifact_ids", "corroboration_count", "single_source", "escalation"], + "additionalProperties": false, + "properties": { + "artifact_ids": { + "type": "array", + "items": { "type": "string" }, + "minItems": 1 + }, + "corroboration_count": { "type": "integer", "minimum": 0 }, + "single_source": { "type": "boolean" }, + "escalation": { "type": "boolean" } + } + } + } +} diff --git a/schemas/osint/provenance_receipt.schema.json b/schemas/osint/provenance_receipt.schema.json new file mode 100644 index 00000000000..c6ffd3c9c36 --- /dev/null +++ b/schemas/osint/provenance_receipt.schema.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://summit.example.com/schemas/osint/provenance_receipt.schema.json", + "title": "OSINT Provenance Receipt", + "type": "object", + "required": [ + "receipt_id", + "artifact_ids", + "source_ids", + "risk_envelope", + "collected_at", + "flags" + ], + "additionalProperties": false, + "properties": { + "receipt_id": { "type": "string" }, + "artifact_ids": { + "type": "array", + "items": { "type": "string" }, + "minItems": 1 + }, + "source_ids": { + "type": "array", + "items": { "type": "string" }, + "minItems": 1 + }, + "risk_envelope": { "type": "string" }, + "collected_at": { "type": "string", "format": "date-time" }, + "flags": { + "type": "array", + "items": { "type": "string" } + } + } +} diff --git a/schemas/osint/redaction_report.schema.json b/schemas/osint/redaction_report.schema.json new file mode 100644 index 00000000000..8898cc03eae --- /dev/null +++ b/schemas/osint/redaction_report.schema.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://summit.example.com/schemas/osint/redaction_report.schema.json", + "title": "OSINT Redaction Report", + "type": "object", + "required": ["report_id", "redacted_fields", "strategy", "total_redactions", "generated_at"], + "additionalProperties": false, + "properties": { + "report_id": { "type": "string" }, + "redacted_fields": { + "type": "array", + "items": { "type": "string" }, + "minItems": 1 + }, + "strategy": { "type": "string" }, + "total_redactions": { "type": "integer", "minimum": 0 }, + "generated_at": { "type": "string", "format": "date-time" } + } +} diff --git a/schemas/osint/risk_envelopes.schema.json b/schemas/osint/risk_envelopes.schema.json new file mode 100644 index 00000000000..cce617ece5d --- /dev/null +++ b/schemas/osint/risk_envelopes.schema.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://summit.example.com/schemas/osint/risk_envelopes.schema.json", + "title": "OSINT Risk Envelopes", + "type": "object", + "required": ["version", "envelopes"], + "additionalProperties": false, + "properties": { + "version": { "type": "integer", "minimum": 1 }, + "envelopes": { + "type": "object", + "minProperties": 1, + "additionalProperties": { + "type": "object", + "required": [ + "description", + "allowed_methods", + "allow_authenticated_access", + "allow_headless_browsing", + "max_alerts_per_run", + "min_corroboration", + "require_human_review_on_escalation" + ], + "additionalProperties": false, + "properties": { + "description": { "type": "string" }, + "allowed_methods": { + "type": "array", + "items": { "type": "string" }, + "minItems": 1 + }, + "allow_authenticated_access": { "type": "boolean" }, + "allow_headless_browsing": { "type": "boolean" }, + "max_alerts_per_run": { "type": "integer", "minimum": 1 }, + "min_corroboration": { "type": "integer", "minimum": 1 }, + "require_human_review_on_escalation": { "type": "boolean" } + } + } + } + } +} diff --git a/schemas/osint/source_registry.schema.json b/schemas/osint/source_registry.schema.json new file mode 100644 index 00000000000..b8e4ceaf71a --- /dev/null +++ b/schemas/osint/source_registry.schema.json @@ -0,0 +1,72 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://summit.example.com/schemas/osint/source_registry.schema.json", + "title": "OSINT Source Registry", + "type": "object", + "required": ["version", "default_risk_envelope", "source_tiers", "source_onboarding_checklist", "sources"], + "additionalProperties": false, + "properties": { + "version": { "type": "integer", "minimum": 1 }, + "default_risk_envelope": { "type": "string" }, + "source_tiers": { + "type": "object", + "minProperties": 1, + "additionalProperties": { + "type": "object", + "required": ["description"], + "additionalProperties": false, + "properties": { + "description": { "type": "string" } + } + } + }, + "source_onboarding_checklist": { + "type": "array", + "items": { "type": "string" }, + "minItems": 1 + }, + "sources": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": [ + "id", + "name", + "tos_class", + "allowed_methods", + "disallowed_methods", + "reliability_tier", + "license", + "rate_limit_per_min", + "geo_restrictions", + "notes" + ], + "additionalProperties": false, + "properties": { + "id": { "type": "string" }, + "name": { "type": "string" }, + "tos_class": { "type": "string" }, + "allowed_methods": { + "type": "array", + "items": { "type": "string" }, + "minItems": 1 + }, + "disallowed_methods": { + "type": "array", + "items": { "type": "string" }, + "minItems": 1 + }, + "reliability_tier": { "type": "string" }, + "license": { "type": "string" }, + "rate_limit_per_min": { "type": "integer", "minimum": 1 }, + "geo_restrictions": { + "type": "array", + "items": { "type": "string" } + }, + "notes": { "type": "string" } + } + } + } + } +}