Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .github/workflows/prove-ores-legal-28-ai-policy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: prove ores-legal 28 AI policy

on:
pull_request:
paths:
- "fixtures/promotion/ores-legal-28/**"
- ".github/workflows/prove-ores-legal-28-ai-policy.yml"

permissions:
contents: read

jobs:
parity:
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- name: Check out exact proof head
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- name: Set up pinned Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020
with:
node-version: 22.16.0
- name: Compare mirrored AI-policy peer authorities
uses: ORESoftware/typespec-json-schema-validator@813d5f021e02574f529a9553b670719f8f10d02c
with:
typespec: fixtures/promotion/ores-legal-28/ai-policy/main.tsp
schema: fixtures/promotion/ores-legal-28/ai-policy/authored.schema.json
report: .typespec-json-schema-validator/ores-legal-28/report.json
contract_ir: .typespec-json-schema-validator/ores-legal-28/contract-ir.json
output_dir: .typespec-json-schema-validator/ores-legal-28/generated
max_probes: "256"
quiet: "true"
- name: Require zero divergence
shell: bash
run: |
set -euo pipefail
node <<'NODE'
const { readFileSync } = require('node:fs');
const report = JSON.parse(readFileSync('.typespec-json-schema-validator/ores-legal-28/report.json', 'utf8'));
if (report.status !== 'passed') throw new Error(`status=${report.status}`);
if (report.zeroUnexplainedFindings !== true) throw new Error('unexplained findings');
if (report.authorities?.precedence !== 'none') throw new Error('peer authority precedence forbidden');
if (report.differential?.summary?.divergences !== 0) throw new Error('differential divergence');
if (report.differential?.summary?.refusals !== 0) throw new Error('differential refusal');
console.log(JSON.stringify(report.differential?.summary ?? {}, null, 2));
NODE
- name: Record source binding
shell: bash
run: |
set -euo pipefail
git hash-object fixtures/promotion/ores-legal-28/ai-policy/main.tsp
git hash-object fixtures/promotion/ores-legal-28/ai-policy/authored.schema.json
echo "source_repo=ores-legal/ores-legal-interfaces"
echo "source_head=8e0c82fcfe4af9e24e856de3ad40968ed151a6bd"
echo "source_pr=28"
100 changes: 100 additions & 0 deletions fixtures/promotion/ores-legal-28/ai-policy/authored.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "urn:ores-legal:ai-policy:v1",
"$defs": {
"AiPolicySubject": {
"type": "object",
"additionalProperties": false,
"unevaluatedProperties": false,
"required": ["subject_ref", "kind"],
"properties": {
"subject_ref": {"type": "string", "minLength": 1, "maxLength": 192},
"kind": {"enum": ["human", "service", "agent"]}
}
},
"AiResourceContext": {
"type": "object",
"additionalProperties": false,
"unevaluatedProperties": false,
"required": ["resource_ref", "resource_kind", "classification", "contains_pii", "contains_secrets", "legal_hold"],
"properties": {
"resource_ref": {"type": "string", "minLength": 1, "maxLength": 192},
"resource_kind": {"enum": ["repository", "source_code", "document", "dataset", "message", "artifact", "tool"]},
"classification": {"enum": ["public", "internal", "confidential", "restricted"]},
"tenant_ref": {"type": "string", "minLength": 1, "maxLength": 128},
"contains_pii": {"type": "boolean"},
"contains_secrets": {"type": "boolean"},
"legal_hold": {"type": "boolean"}
}
},
"AiExecutionContext": {
"type": "object",
"additionalProperties": false,
"unevaluatedProperties": false,
"required": ["action", "provider_class", "model_class", "environment", "training_use", "retention"],
"properties": {
"action": {"enum": ["read", "summarize", "generate", "modify", "execute", "publish", "export"]},
"provider_class": {"type": "string", "minLength": 1, "maxLength": 128},
"model_class": {"type": "string", "minLength": 1, "maxLength": 128},
"environment": {"enum": ["local", "sandbox", "ci", "server", "external_provider"]},
"training_use": {"enum": ["prohibited", "provider_default", "explicitly_allowed"]},
"retention": {"enum": ["none", "ephemeral", "bounded", "provider_default"]}
}
},
"AiPolicyConstraint": {
"type": "object",
"additionalProperties": false,
"unevaluatedProperties": false,
"required": ["kind"],
"properties": {
"kind": {"enum": ["human_review", "tool_allowlist", "provider_allowlist", "no_external_export", "no_training", "ephemeral_retention", "sandbox_required", "redaction_required"]},
"value": {"type": "string", "minLength": 1, "maxLength": 192}
}
},
"AiPolicyEvaluationRequest": {
"type": "object",
"additionalProperties": false,
"unevaluatedProperties": false,
"required": ["request_id", "subject", "resource", "execution", "policy_bundle_sha256", "evaluated_at"],
"properties": {
"request_id": {"type": "string", "pattern": "^[A-Za-z0-9_-]{16,128}$"},
"subject": {"$ref": "#/$defs/AiPolicySubject"},
"resource": {"$ref": "#/$defs/AiResourceContext"},
"execution": {"$ref": "#/$defs/AiExecutionContext"},
"policy_bundle_sha256": {"type": "string", "pattern": "^[a-f0-9]{64}$"},
"evaluated_at": {"type": "integer", "minimum": 1, "maximum": 9007199254740991}
}
},
"AiPolicyDecision": {
"type": "object",
"additionalProperties": false,
"unevaluatedProperties": false,
"required": ["decision_id", "policy_version", "result", "constraints", "request_sha256", "compiled_policy_sha256", "source_policy_sha256", "decided_at"],
"properties": {
"decision_id": {"type": "string", "pattern": "^[A-Za-z0-9_-]{16,128}$"},
"policy_version": {"type": "string", "minLength": 1, "maxLength": 128},
"result": {"enum": ["allow", "deny", "require_review", "allow_with_constraints"]},
"constraints": {"type": "array", "items": {"$ref": "#/$defs/AiPolicyConstraint"}},
"request_sha256": {"type": "string", "pattern": "^[a-f0-9]{64}$"},
"compiled_policy_sha256": {"type": "string", "pattern": "^[a-f0-9]{64}$"},
"source_policy_sha256": {"type": "string", "pattern": "^[a-f0-9]{64}$"},
"decided_at": {"type": "integer", "minimum": 1, "maximum": 9007199254740991},
"expires_at": {"type": "integer", "minimum": 1, "maximum": 9007199254740991}
}
},
"AiPolicyReviewReceipt": {
"type": "object",
"additionalProperties": false,
"unevaluatedProperties": false,
"required": ["review_id", "decision_id", "reviewer_ref", "result", "reviewed_resource_sha256", "reviewed_at"],
"properties": {
"review_id": {"type": "string", "pattern": "^[A-Za-z0-9_-]{16,128}$"},
"decision_id": {"type": "string", "pattern": "^[A-Za-z0-9_-]{16,128}$"},
"reviewer_ref": {"type": "string", "minLength": 1, "maxLength": 192},
"result": {"enum": ["approved", "rejected"]},
"reviewed_resource_sha256": {"type": "string", "pattern": "^[a-f0-9]{64}$"},
"reviewed_at": {"type": "integer", "minimum": 1, "maximum": 9007199254740991}
}
}
}
}
71 changes: 71 additions & 0 deletions fixtures/promotion/ores-legal-28/ai-policy/main.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import "@typespec/json-schema";
using TypeSpec.JsonSchema;

@jsonSchema
namespace OresLegal.AiPolicy;

@extension("additionalProperties", false)
model AiPolicySubject {
@minLength(1) @maxLength(192) subject_ref: string;
kind: "human" | "service" | "agent";
}

@extension("additionalProperties", false)
model AiResourceContext {
@minLength(1) @maxLength(192) resource_ref: string;
resource_kind: "repository" | "source_code" | "document" | "dataset" | "message" | "artifact" | "tool";
classification: "public" | "internal" | "confidential" | "restricted";
@minLength(1) @maxLength(128) tenant_ref?: string;
contains_pii: boolean;
contains_secrets: boolean;
legal_hold: boolean;
}

@extension("additionalProperties", false)
model AiExecutionContext {
action: "read" | "summarize" | "generate" | "modify" | "execute" | "publish" | "export";
@minLength(1) @maxLength(128) provider_class: string;
@minLength(1) @maxLength(128) model_class: string;
environment: "local" | "sandbox" | "ci" | "server" | "external_provider";
training_use: "prohibited" | "provider_default" | "explicitly_allowed";
retention: "none" | "ephemeral" | "bounded" | "provider_default";
}

@extension("additionalProperties", false)
model AiPolicyConstraint {
kind: "human_review" | "tool_allowlist" | "provider_allowlist" | "no_external_export" | "no_training" | "ephemeral_retention" | "sandbox_required" | "redaction_required";
@minLength(1) @maxLength(192) value?: string;
}

@extension("additionalProperties", false)
model AiPolicyEvaluationRequest {
@pattern("^[A-Za-z0-9_-]{16,128}$") request_id: string;
subject: AiPolicySubject;
resource: AiResourceContext;
execution: AiExecutionContext;
@pattern("^[a-f0-9]{64}$") policy_bundle_sha256: string;
@minValue(1) @maxValue(9007199254740991) evaluated_at: integer;
}

@extension("additionalProperties", false)
model AiPolicyDecision {
@pattern("^[A-Za-z0-9_-]{16,128}$") decision_id: string;
@minLength(1) @maxLength(128) policy_version: string;
result: "allow" | "deny" | "require_review" | "allow_with_constraints";
constraints: AiPolicyConstraint[];
@pattern("^[a-f0-9]{64}$") request_sha256: string;
@pattern("^[a-f0-9]{64}$") compiled_policy_sha256: string;
@pattern("^[a-f0-9]{64}$") source_policy_sha256: string;
@minValue(1) @maxValue(9007199254740991) decided_at: integer;
@minValue(1) @maxValue(9007199254740991) expires_at?: integer;
}

@extension("additionalProperties", false)
model AiPolicyReviewReceipt {
@pattern("^[A-Za-z0-9_-]{16,128}$") review_id: string;
@pattern("^[A-Za-z0-9_-]{16,128}$") decision_id: string;
@minLength(1) @maxLength(192) reviewer_ref: string;
result: "approved" | "rejected";
@pattern("^[a-f0-9]{64}$") reviewed_resource_sha256: string;
@minValue(1) @maxValue(9007199254740991) reviewed_at: integer;
}
Loading