From 1cca8ca6408ad1bd7f1813786bbc7a2528bb14f0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 17:09:33 +0000 Subject: [PATCH 1/3] =?UTF-8?q?docs:=20Phase=201=20=E2=80=93=20prose=20doc?= =?UTF-8?q?umentation=20(README,=20ARCHITECTURE,=20CONTRIBUTING,=20CHANGEL?= =?UTF-8?q?OG,=20ADRs,=20schemas/README=20fix,=20examples/README,=20semant?= =?UTF-8?q?ic/README,=20PR=20template)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agent-Logs-Url: https://github.com/SourceOS-Linux/sourceos-spec/sessions/8b9ff02b-0b12-4bf8-8f38-efe8f63363c9 Co-authored-by: mdheller <21163552+mdheller@users.noreply.github.com> --- .github/PULL_REQUEST_TEMPLATE.md | 44 +++- .gitignore | 3 + ARCHITECTURE.md | 250 ++++++++++++++++++++++ CHANGELOG.md | 68 ++++++ CONTRIBUTING.md | 205 ++++++++++++++++++ README.md | 153 +++++++++++--- docs/adr/0000-template.md | 28 +++ docs/adr/0001-urn-identity-scheme.md | 52 +++++ docs/adr/0002-typed-policy-condition.md | 55 +++++ docs/adr/0003-agent-plane-patch-files.md | 47 +++++ docs/adr/0004-json-schema-2020-12.md | 42 ++++ examples/README.md | 115 ++++++++++ schemas/README.md | 255 ++++++++++++++++------- semantic/README.md | 95 +++++++++ 14 files changed, 1311 insertions(+), 101 deletions(-) create mode 100644 ARCHITECTURE.md create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 docs/adr/0000-template.md create mode 100644 docs/adr/0001-urn-identity-scheme.md create mode 100644 docs/adr/0002-typed-policy-condition.md create mode 100644 docs/adr/0003-agent-plane-patch-files.md create mode 100644 docs/adr/0004-json-schema-2020-12.md create mode 100644 examples/README.md create mode 100644 semantic/README.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 11ffada..9a8270d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1 +1,43 @@ -ready_for_review: true \ No newline at end of file +## Description of change + + + +## Type of change + +- [ ] New schema (additive) +- [ ] Modified schema — additive (new optional field, new enum value) +- [ ] Modified schema — breaking (required field added/removed, type narrowed) +- [ ] New or updated example +- [ ] OpenAPI / AsyncAPI change +- [ ] Documentation only +- [ ] Bug fix + +## Checklist + +- [ ] Schema file created/updated in `schemas/` with `"description"` on schema and all properties +- [ ] `"additionalProperties": false` present on all object types in the schema +- [ ] Example file created/updated in `examples/` and passes `ajv validate` +- [ ] `schemas/README.md` updated (family table row added/updated) +- [ ] `openapi.yaml` or patch updated with `summary`, `description`, `tags`, and error responses +- [ ] `asyncapi.yaml` or patch updated with channel and message descriptions +- [ ] `CHANGELOG.md` updated under `[Unreleased]` +- [ ] `specVersion` bumped if this is a breaking change +- [ ] ADR created in `docs/adr/` if the design involves a non-obvious choice +- [ ] `semantic/context.jsonld` and `hydra.jsonld` updated for new first-class types + +## Validation commands run + +```bash +# Schema validation +ajv validate -s schemas/.json -d examples/.json + +# OpenAPI lint +spectral lint openapi.yaml + +# AsyncAPI lint +asyncapi validate asyncapi.yaml +``` + +## Related issues / ADRs + + diff --git a/.gitignore b/.gitignore index 8d62e90..6df2fb5 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ venv/ # Build dist/ build/ + +# GitHub API artifacts accidentally fetched locally +pulls/ diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..0b120d1 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,250 @@ +# Architecture + +This document describes the structural design of the SourceOS/SociOS Typed Contracts specification: the two-plane model, schema families, the governance lifecycle, and the URN identity scheme. + +--- + +## 1 Two-plane model + +The specification is split into two composable planes, each with its own OpenAPI patch file and AsyncAPI patch file. + +``` +┌──────────────────────────────────────────────────────────────┐ +│ METADATA PLANE │ +│ openapi.yaml · asyncapi.yaml │ +│ │ +│ Physical assets → Datasets → Fields → Glossary │ +│ Policies / Decisions / Tokens / Obligations │ +│ Workflows / Runs / Provenance │ +│ Collaboration (Comments, Ratings, Communities) │ +│ Agreements │ +└──────────────────────┬───────────────────────────────────────┘ + │ references via URNs +┌──────────────────────▼───────────────────────────────────────┐ +│ AGENT PLANE │ +│ openapi.agent-plane.patch.yaml · asyncapi.agent-plane.patch.yaml │ +│ │ +│ AgentSessions → ExecutionDecisions → SessionReceipts │ +│ SkillManifests · MemoryEntries · TelemetryEvents │ +│ FrustrationSignals · SessionReviews │ +└──────────────────────────────────────────────────────────────┘ +``` + +**Metadata plane** (`openapi.yaml` / `asyncapi.yaml`): manages cataloguing, governance, and execution of data workloads. It is the source of truth for what data exists, who may access it, and what happened to it. + +**Agent plane** (`openapi.agent-plane.patch.yaml` / `asyncapi.agent-plane.patch.yaml`): manages autonomous agent sessions that operate *on* the metadata plane. An agent session records which skills and memories it used, every `ExecutionDecision` it made, and its outcome via a `SessionReceipt`. + +The patch files are **additive fragments**, not standalone specs. An implementation merges each patch into the base spec at deploy time. + +--- + +## 2 Schema families + +### Family 1 – Physical Assets +Describes where data physically lives. + +| Schema | Purpose | +|--------|---------| +| `Connector` | A named, typed connection (S3, GCS, RDBMS, Kafka, …) | +| `PhysicalAsset` | A specific resource reachable through a `Connector` | + +### Family 2 – Glossary +Shared business vocabulary anchored to external authority systems. + +| Schema | Purpose | +|--------|---------| +| `GlossaryTerm` | A defined term with synonyms and classification tags | +| `AuthorityLink` | A pointer to an external controlled vocabulary (e.g. SNOMED, ISO) | + +### Family 3 – Governance +The policy engine: evaluates access requests and issues short-lived capability tokens. + +| Schema | Purpose | +|--------|---------| +| `Policy` | A named access policy with subjects, objects, purposes, rules, and obligations | +| `Rule` | A single `permit`/`deny` rule with an optional `PolicyCondition` | +| `PolicyCondition` | A rule expression in one of four languages: `jsonlogic`, `cel`, `rego`, `cedar` | +| `SubjectSelector` / `ObjectSelector` | Match clauses for subjects and objects in a `Policy` scope | +| `PolicyDecision` | The immutable audit record of an `/evaluate` call | +| `CapabilityToken` | A short-lived, signed access grant derived from a `PolicyDecision` | +| `Obligation` | An action that must be performed before (`pre`), after (`post`), or during (`runtime`) an operation | +| `Exception` | A time-limited exemption attached to a `Policy` | +| `PolicyBinding` | Associates a `Policy` with a `WorkflowSpec` or `SkillManifest` | + +### Family 4 – Collaboration +Human feedback attached to any addressable object. + +| Schema | Purpose | +|--------|---------| +| `Comment` | A free-text annotation on any object identified by a URN | +| `Rating` | A 1–5 integer rating on any object | +| `Community` | A named group of subject URNs | + +### Family 5 – Models / Schemas +The logical view of data: types, constraints, tags, and quality. + +| Schema | Purpose | +|--------|---------| +| `SchemaDefinition` | A named, versioned schema composed of `EntityField`s | +| `EntityField` | A field descriptor inside a `SchemaDefinition` | +| `Field` | A fully annotated, quality-profiled field attached to a live `Dataset` | +| `TagAssignment` | A classification tag with confidence, source, and review provenance | +| `ValidValues` | Enumeration, range, or regex constraint on a field | +| `QualityMetric` | A named quality dimension (completeness, validity, …) with a 0–1 score | +| `ProfileStats` | Statistical profile of a column (row count, nulls, distinct values, top-N) | + +### Family 6 – Agreements +Legal and operational data-sharing agreements. + +| Schema | Purpose | +|--------|---------| +| `Agreement` | A data-sharing agreement between one or more parties | +| `Party` | A named signatory (person, org, or service) with optional authority links | + +### Execution / Provenance family +Tracks *what ran*, *with what inputs*, and *what was produced*. + +| Schema | Purpose | +|--------|---------| +| `Dataset` | A logical view of a `PhysicalAsset` with governance and lifecycle metadata | +| `DataRef` | A typed pointer to a dataset, asset, stream topic, or file | +| `WorkloadSpec` | A container, Spark job, function, or stream processor to execute | +| `DataSphere` | A bounded execution environment with network and storage controls | +| `RunRecord` | The audit record of a single workload execution | +| `WorkflowSpec` | A directed acyclic graph of `WorkflowNode`s connected by `WorkflowEdge`s | +| `WorkflowNode` | A single node in a `WorkflowSpec`, wrapping a `WorkloadSpec` | +| `WorkflowEdge` | A directed edge between two `WorkflowNode` IDs | +| `Trigger` | How a workflow is activated: schedule (cron), event, or manual | +| `ProvenanceRecord` | A W3C PROV-compatible record linking a `RunRecord` to its input/output entities | +| `MappingSpec` | A field-to-field mapping with multi-method confidence evidence | +| `MappingEvidence` | A single piece of evidence for a `MappingSpec` (label similarity, value overlap, …) | +| `EventEnvelope` | The universal event wrapper for all AsyncAPI channel messages | + +### Agent Plane family +Manages autonomous agent sessions and their decisions. + +| Schema | Purpose | +|--------|---------| +| `AgentSession` | A single autonomous agent session with role, mode, substrate, and surface | +| `ExecutionSurface` | The sandboxing, network, and filesystem constraints of an agent's environment | +| `ExecutionDecision` | An immutable record of an agent's allow/deny/ask/defer/rewrite decision | +| `SkillManifest` | A declared skill with activation rules, requirements, and policy bindings | +| `MemoryEntry` | A persistent agent memory of kind `rule`, `learned`, or `recap` | +| `SessionReceipt` | The final outcome record for an `AgentSession` | +| `SessionReview` | A post-session learning review linking to extracted memory entries | +| `TelemetryEvent` | A structured log event from within an agent session | +| `FrustrationSignal` | A behavioural signal indicating agent or user difficulty | + +### Release / Experiments family + +| Schema | Purpose | +|--------|---------| +| `ExperimentFlag` | A feature flag with lifecycle states: off → shadow → internal → beta → on → retired | +| `RolloutPolicy` | Audience-based rollout rules for an `ExperimentFlag` | +| `ReleaseReceipt` | A verified release record with artifact hashes and gate results | + +--- + +## 3 Governance lifecycle + +A complete governance-gated data access follows this sequence: + +``` +User / Service + │ + │ POST /v2/decisions/evaluate + │ { subject, object, purpose } + ▼ +PolicyDecision ──────────────► CapabilityToken (POST /v2/tokens/issue) + │ + │ obligations attached + ▼ +RunRecord ──────────────────────────────────────► ProvenanceRecord + │ + │ references CapabilityToken + PolicyDecision + ▼ +EventEnvelope (srcos.v2.run.events) +``` + +1. The caller sends a policy evaluation request to `/v2/decisions/evaluate`. +2. The engine matches the request against all applicable `Policy` documents and returns a `PolicyDecision` (permit / deny / permitWithObligations). +3. If permitted, the caller calls `/v2/tokens/issue` to receive a `CapabilityToken` that is scoped to the approved datasets, fields, and operations. +4. The workload executes inside a `DataSphere`, referencing the `CapabilityToken`. +5. The `RunRecord` is stored at `/v2/runs` and a `ProvenanceRecord` at `/v2/provenance`. +6. Both events are published to the appropriate AsyncAPI channels. + +--- + +## 4 URN identity scheme + +Every top-level object carries a stable `id` field that is a URN of the form: + +``` +urn:srcos:: +``` + +| Type | URN prefix | Example | +|------|-----------|---------| +| Connector | `urn:srcos:connector:` | `urn:srcos:connector:local_s3` | +| PhysicalAsset | `urn:srcos:asset:` | `urn:srcos:asset:lake_curated_health` | +| Dataset | `urn:srcos:dataset:` | `urn:srcos:dataset:health_obs` | +| Field | `urn:srcos:field:` | `urn:srcos:field:dob` | +| SchemaDefinition | `urn:srcos:schema:` | `urn:srcos:schema:health_obs_v1` | +| GlossaryTerm | `urn:srcos:glossary:` | `urn:srcos:glossary:dob` | +| Agreement | `urn:srcos:agreement:` | `urn:srcos:agreement:default` | +| Party | `urn:srcos:party:` | `urn:srcos:party:self` | +| Policy | `urn:srcos:policy:` | `urn:srcos:policy:export_health_restricted` | +| PolicyDecision | `urn:srcos:decision:` | `urn:srcos:decision:aa11bb22` | +| CapabilityToken | _(plain string `tokenId`)_ | `tok_123` | +| RunRecord | `urn:srcos:run:` | `urn:srcos:run:77cc88dd` | +| ProvenanceRecord | `urn:srcos:prov:` | `urn:srcos:prov:001` | +| WorkflowSpec | `urn:srcos:workflow:` | `urn:srcos:workflow:etl_v1` | +| WorkloadSpec | `urn:srcos:workload:` | `urn:srcos:workload:obfuscator_v1` | +| DataSphere | `urn:srcos:sphere:` | `urn:srcos:sphere:personal_curated` | +| MappingSpec | `urn:srcos:mapping:` | `urn:srcos:mapping:001` | +| Comment | `urn:srcos:comment:` | `urn:srcos:comment:001` | +| Rating | `urn:srcos:rating:` | `urn:srcos:rating:001` | +| Community | `urn:srcos:community:` | `urn:srcos:community:data-team` | +| EventEnvelope | `urn:srcos:event:` | `urn:srcos:event:001` | +| AgentSession | `urn:srcos:session:` | `urn:srcos:session:s001` | +| ExecutionDecision | `urn:srcos:exec-decision:` | `urn:srcos:exec-decision:ed001` | +| SkillManifest | `urn:srcos:skill:` | `urn:srcos:skill:pdf-reader` | +| MemoryEntry | `urn:srcos:memory:` | `urn:srcos:memory:m001` | +| SessionReceipt | `urn:srcos:receipt:session:` | `urn:srcos:receipt:session:r001` | +| SessionReview | `urn:srcos:session-review:` | `urn:srcos:session-review:sr001` | +| TelemetryEvent | `urn:srcos:telemetry:` | `urn:srcos:telemetry:t001` | +| FrustrationSignal | `urn:srcos:frustration:` | `urn:srcos:frustration:f001` | +| ExperimentFlag | `urn:srcos:flag:` | `urn:srcos:flag:new-ui` | +| RolloutPolicy | `urn:srcos:rollout:` | `urn:srcos:rollout:rp001` | +| ReleaseReceipt | `urn:srcos:release-receipt:` | `urn:srcos:release-receipt:v2.0.0` | + +`local-id` is a URL-safe slug chosen by the producer. It must be unique within its type namespace. + +--- + +## 5 Patch-file composition model + +The agent-plane functionality is delivered as two patch files rather than folded into the base specs. This keeps the metadata-plane spec self-contained for implementations that do not need the agent plane. + +At runtime, merge the patches into the base specs before serving or generating code: + +```bash +# OpenAPI merge example (using openapi-merge-cli) +npx openapi-merge-cli \ + --config merge-config.yaml # inputs: openapi.yaml + openapi.agent-plane.patch.yaml + +# AsyncAPI merge (using asyncapi-bundler) +npx @asyncapi/bundler asyncapi.yaml asyncapi.agent-plane.patch.yaml -o asyncapi.merged.yaml +``` + +The patches are **additive only** — they never override or delete paths from the base spec. + +--- + +## 6 Semantic overlay + +`semantic/context.jsonld` provides a JSON-LD `@context` that maps schema type names to stable IRIs under `https://schemas.srcos.ai/v2/`. + +`semantic/hydra.jsonld` provides a `hydra:ApiDocumentation` fragment that can be merged with the JSON-LD context to make the REST API self-describing. + +See [semantic/README.md](semantic/README.md) for usage details. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..b60df6d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,68 @@ +# Changelog + +All notable changes to the SourceOS/SociOS Typed Contracts specification are documented here. + +The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +--- + +## [Unreleased] + +### Added +- `description` fields on all 54 schemas and all properties (non-breaking documentation improvement) +- `ARCHITECTURE.md` — two-plane architecture, schema families, governance lifecycle, URN table +- `CONTRIBUTING.md` — schema authoring conventions, URN naming guide, PR checklist +- `docs/adr/` — Architecture Decision Records for key design choices +- `examples/README.md` — guide to the example payloads +- `semantic/README.md` — guide to the JSON-LD and Hydra overlays +- Expanded `semantic/context.jsonld` to cover all 54 schema types +- Expanded `semantic/hydra.jsonld` to cover all API resource classes +- OpenAPI: `summary`, `description`, `tags`, security scheme, and error responses (`400`, `401`, `403`, `422`) on every operation +- AsyncAPI: channel and message `description` fields; Kafka `bindings` on every channel +- Missing `examples/` files for all agent-plane and supporting schemas + +### Changed +- `README.md` rewritten as a proper project introduction with repo layout, schema family table, quick-start commands, and contribution links +- `schemas/README.md` corrected: URN patterns now match actual schema `pattern` constraints; example JSON replaced with accurate, AJV-validated payloads; all six schema families documented +- `.github/PULL_REQUEST_TEMPLATE.md` expanded to a full structured PR checklist + +### Fixed +- `schemas/README.md` used `urn:sourceos:` prefix — corrected to `urn:srcos:` throughout + +--- + +## [2.0.0] — 2025-12-24 + +### Added +- `Agreement` and `Party` schemas (Area 6: Agreements) +- `GlossaryTerm` and `AuthorityLink` schemas (Area 2: Glossary) +- `Connector` and `PhysicalAsset` schemas (Area 1: Physical Assets) +- `SchemaDefinition`, `EntityField`, `ValidValues` schemas (Area 5: Models/Schemas) +- `ProvenanceRecord` schema with W3C PROV-compatible entity roles +- `Comment`, `Rating`, `Community` schemas (Area 4: Collaboration) +- `PolicyCondition` with typed expression language (`jsonlogic`, `cel`, `rego`, `cedar`) +- `MappingSpec` and `MappingEvidence` schemas for field-to-field lineage +- `TagAssignment` with confidence, source provenance, and review record +- Agent-plane schemas: `AgentSession`, `ExecutionDecision`, `ExecutionSurface`, `SkillManifest`, `MemoryEntry`, `SessionReceipt`, `SessionReview`, `TelemetryEvent`, `FrustrationSignal` +- Release/experiment schemas: `ExperimentFlag`, `RolloutPolicy`, `ReleaseReceipt` +- Hydra/JSON-LD semantic overlay (`semantic/context.jsonld`, `semantic/hydra.jsonld`) +- Agent-plane OpenAPI patch (`openapi.agent-plane.patch.yaml`) +- Agent-plane AsyncAPI patch (`asyncapi.agent-plane.patch.yaml`) + +### Changed +- `Dataset` now requires explicit `assetRef` and `schemaRef` URN references (previously physical storage was implicit) +- `Policy` rules upgraded from a flat structure to `Rule` + `PolicyCondition` with a declared `language` field +- All IDs changed from opaque strings to `urn:srcos:` URNs with enforced `pattern` constraints + +### Removed +- Implicit physical fields from `Dataset` (replaced by `PhysicalAsset` + `Connector` references) + +--- + +## [1.0.0] — (initial, pre-repository) + +Initial typed contract set covering: +- `Dataset`, `Field`, `Policy`, `PolicyDecision`, `CapabilityToken` +- `RunRecord`, `WorkflowSpec`, `WorkflowNode`, `WorkflowEdge`, `WorkloadSpec` +- `DataSphere`, `DataRef`, `Obligation`, `SubjectContext`, `ObjectContext` +- `EventEnvelope`, `Link` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..b787cbc --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,205 @@ +# Contributing to SourceOS/SociOS Typed Contracts + +Thank you for contributing to the spec! This guide covers the conventions you must follow so that every schema remains machine-readable, internally consistent, and backward-compatible. + +--- + +## Table of contents + +1. [Pre-requisites](#pre-requisites) +2. [Repository structure recap](#repository-structure-recap) +3. [Adding a new schema](#adding-a-new-schema) +4. [Modifying an existing schema](#modifying-an-existing-schema) +5. [URN naming guide](#urn-naming-guide) +6. [Updating the API specs](#updating-the-api-specs) +7. [Writing examples](#writing-examples) +8. [Pull-request checklist](#pull-request-checklist) +9. [Breaking vs additive changes](#breaking-vs-additive-changes) + +--- + +## Pre-requisites + +```bash +# Validate schemas and examples with AJV (Node ≥ 18) +npm install -g ajv-cli + +# Validate OpenAPI spec +npm install -g @stoplight/spectral-cli + +# Validate AsyncAPI spec +npm install -g @asyncapi/cli +``` + +--- + +## Repository structure recap + +``` +schemas/ JSON Schema (draft 2020-12) — one file per type +examples/ One conforming example JSON per schema type +openapi.yaml Metadata-plane REST API +openapi.agent-plane.patch.yaml Agent-plane additive REST patch +asyncapi.yaml Metadata-plane event channels +asyncapi.agent-plane.patch.yaml Agent-plane additive event channels +semantic/ JSON-LD context + Hydra API documentation +docs/adr/ Architecture Decision Records +``` + +--- + +## Adding a new schema + +### 1 Create the schema file + +Save it to `schemas/.json`. The filename must be `PascalCase` and match the `title` field exactly. + +**Required top-level fields:** + +```json +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.srcos.ai/v2/.json", + "title": "", + "description": "One-sentence description of what this object represents.", + "type": "object", + "additionalProperties": false, + "required": ["id", "type", "specVersion", ...], + "properties": { + "id": { + "type": "string", + "pattern": "^urn:srcos::", + "description": "Stable URN identifier. Pattern: urn:srcos::" + }, + "type": { + "const": "", + "description": "Discriminator constant — always \"\"." + }, + "specVersion": { + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." + } + } +} +``` + +**Rules:** +- Every property **must** have a `"description"` field (or a `$ref` that resolves to a described type). +- `"additionalProperties": false` is required on every object. +- Nullable fields use `"type": ["", "null"]`. +- Timestamps use `"type": "string", "format": "date-time"`. +- All cross-object references use a URN `"pattern"` constraint that matches the target type's URN prefix. + +### 2 Add the schema to the appropriate family + +Update `schemas/README.md` — add a row to the correct family table. + +### 3 Add a conforming example + +Create `examples/.json` (lowercase filename). The example must validate against the schema: + +```bash +ajv validate -s schemas/.json -d examples/.json +``` + +### 4 Expose the type in the OpenAPI spec + +Add a `POST /v2/` operation to `openapi.yaml` (metadata-plane types) or `openapi.agent-plane.patch.yaml` (agent-plane types). Every operation **must** include `summary`, `description`, `tags`, and at minimum `200`, `400`, and `422` responses. + +### 5 Add an AsyncAPI channel (if the type generates events) + +Add the channel to `asyncapi.yaml` or `asyncapi.agent-plane.patch.yaml`. Include a `description` on both the channel and the message. + +### 6 Update the semantic context (if needed) + +If the new type is a first-class domain concept (not a supporting sub-type), add it to `semantic/context.jsonld` and add a `hydra:supportedClass` entry to `semantic/hydra.jsonld`. + +### 7 Write an ADR (if the design involves a non-obvious choice) + +Create `docs/adr/NNN-.md` using the template at `docs/adr/0000-template.md`. + +--- + +## Modifying an existing schema + +| Change type | Allowed? | Notes | +|-------------|----------|-------| +| Add optional property | ✅ Minor bump | Existing documents remain valid | +| Add required property | ⚠️ Major bump | Existing documents become invalid — must bump `specVersion` major and log in `CHANGELOG.md` + ADR | +| Remove property | ⚠️ Major bump | Same as above | +| Narrow a type (e.g. `string` → `enum`) | ⚠️ Major bump | | +| Widen a type (e.g. add enum value) | ✅ Minor bump | | +| Fix a `pattern` bug | ✅ Patch bump | | +| Change a `description` | ✅ No version bump | | + +--- + +## URN naming guide + +All stable identifiers follow the scheme `urn:srcos::`. + +- **`type-slug`** is lowercase, hyphen-separated, and maps one-to-one to a schema title (see the full table in [ARCHITECTURE.md](ARCHITECTURE.md#4-urn-identity-scheme)). +- **`local-id`** is a URL-safe slug chosen by the producer. It must be unique within the type namespace. Recommended format: `[a-z0-9][a-z0-9_-]*`. +- Use existing URN prefixes — do **not** invent new slugs without updating `ARCHITECTURE.md` and this guide. + +--- + +## Updating the API specs + +- `openapi.yaml` and `openapi.agent-plane.patch.yaml` follow OpenAPI 3.0.3. +- All operations must have: `operationId` (camelCase verb + noun), `summary` (≤ 10 words), `description`, at least one `tags` entry, and response codes `200`, `400`, `401`, `403`, `422`. +- `asyncapi.yaml` and `asyncapi.agent-plane.patch.yaml` follow AsyncAPI 2.6.0. +- All channels must have a `description`. All messages must have `name`, `title`, `summary`, and `description`. + +Validate before committing: + +```bash +spectral lint openapi.yaml +asyncapi validate asyncapi.yaml +``` + +--- + +## Writing examples + +- One file per schema type, saved as `examples/.json` (all-lowercase filename matching the schema `title` lowercased). +- The example must be a **complete**, valid document — all required fields present. +- Use the shared cross-reference URNs already established in other examples (e.g. `urn:srcos:dataset:health_obs`) so the example set tells a coherent end-to-end story. +- Validate the example before committing: + +```bash +ajv validate -s schemas/.json -d examples/.json +``` + +--- + +## Pull-request checklist + +The PR template will remind you, but here is the complete list: + +- [ ] Schema file created/updated in `schemas/` +- [ ] `"description"` present on schema and all properties +- [ ] `"additionalProperties": false` on all object types +- [ ] Example file created/updated in `examples/` and passes AJV validation +- [ ] `schemas/README.md` updated (schema family table) +- [ ] `openapi.yaml` or patch updated with full operation metadata +- [ ] `asyncapi.yaml` or patch updated with channel/message descriptions +- [ ] `CHANGELOG.md` updated +- [ ] ADR created in `docs/adr/` if design rationale is non-obvious +- [ ] `semantic/context.jsonld` and `hydra.jsonld` updated for first-class types +- [ ] `specVersion` bumped if required (see [Breaking vs additive changes](#breaking-vs-additive-changes)) + +--- + +## Breaking vs additive changes + +A **breaking change** is any change that can cause a previously valid document to become invalid, or a previously invalid document to become valid in an unexpected way. Breaking changes: + +1. Must bump the `specVersion` major version in the affected schema(s). +2. Must be documented in `CHANGELOG.md` under a new `## [X.0.0]` heading. +3. Must have a corresponding ADR in `docs/adr/`. +4. Should include a migration guide in the ADR. + +An **additive change** (new optional field, new enum value, new endpoint) bumps the minor version only. + +A **bug fix** (pattern correction, description improvement) bumps the patch version only. diff --git a/README.md b/README.md index 074ff78..4d1ed7c 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,131 @@ -# SourceOS/SociOS Typed Contracts Starter Kit (v2) - -This revision closes the biggest implementability gaps from v1: -- Adds Agreement + Glossary + Connector/Asset + SchemaDefinition + Provenance + Collaboration objects -- Upgrades policy conditions to a typed `PolicyCondition` with a declared language (jsonlogic/cel/rego/cedar) -- Adds a minimal Hydra/JSON-LD semantic overlay (semantic/context.jsonld + semantic/hydra.jsonld) -- Upgrades Dataset to reference Asset + Schema + Agreements explicitly (no implicit physical fields) - -## Why this matters -If a contract bundle does not cover agreements, glossary, and asset connectors, the metadata plane cannot unify governance and meaning end-to-end. -We now have a closed set of object families that directly correspond to the Open Metadata Types taxonomy areas: -- Area 1: Physical assets -> Connector, PhysicalAsset -- Area 2: Glossary -> GlossaryTerm -- Area 3: Governance -> Policy/Decision/Token/Obligations -- Area 4: Collaboration -> Comment/Rating/Community -- Area 5: Models/Schemas -> SchemaDefinition, EntityField, ValidValues -- Area 6: Agreements -> Agreement, Party - -## Minimal implementation path (practical) -1) Schema validation: AJV (Node) or jsonschema (Python). -2) Codegen: TypeScript types (quicktype) or Python models (datamodel-code-generator for Pydantic). -3) API service: OpenAPI -> FastAPI scaffold. -4) Event spine: AsyncAPI -> Kafka topics with schema validation at the producer/consumer boundaries. +# SourceOS/SociOS Typed Contracts + +**SourceOS/SociOS Typed Contracts** is the canonical, machine-readable specification for the SourceOS metadata governance platform and the SociOS agent plane. It defines the full set of JSON Schemas, an OpenAPI REST surface, an AsyncAPI event spine, and a JSON-LD / Hydra semantic overlay that together make up the "contract layer" every implementation component must satisfy. + +> **Spec version:** `2.0.0`  |  **License:** see [LICENSE](LICENSE) + +--- + +## Why this repository exists + +A metadata governance platform can only unify data meaning, policy, provenance, and agent execution if every component agrees on the *shape* of the objects it exchanges. This repository is that shared agreement. Downstream consumers include: + +- **API services** — scaffolded from `openapi.yaml` (metadata plane) and `openapi.agent-plane.patch.yaml` (agent plane). +- **Event consumers** — Kafka topics declared in `asyncapi.yaml` + `asyncapi.agent-plane.patch.yaml`. +- **Validators** — AJV (Node.js) or `jsonschema` (Python) loaded from `schemas/`. +- **Code generators** — TypeScript types via [quicktype](https://quicktype.io); Python models via [datamodel-code-generator](https://github.com/koxudaxi/datamodel-code-generator). +- **Semantic tooling** — JSON-LD context + Hydra API documentation in `semantic/`. + +--- + +## Repository layout + +``` +sourceos-spec/ +├── README.md # This file +├── ARCHITECTURE.md # Two-plane architecture, schema families, lifecycle +├── CONTRIBUTING.md # How to add / modify schemas and API specs +├── CHANGELOG.md # Spec version history +├── LICENSE +│ +├── openapi.yaml # Metadata-plane REST API (v2) +├── openapi.agent-plane.patch.yaml # Additive agent-plane REST endpoints +├── asyncapi.yaml # Metadata-plane event channels +├── asyncapi.agent-plane.patch.yaml # Agent-plane event channels +│ +├── schemas/ # 54 JSON Schema (draft 2020-12) files +│ └── README.md # Schema catalog and URN patterns +│ +├── examples/ # Conforming example payloads (one per type) +│ └── README.md +│ +├── semantic/ # JSON-LD context + Hydra API documentation +│ └── README.md +│ +└── docs/ + └── adr/ # Architecture Decision Records +``` + +--- + +## Schema families + +The 54 schemas are organised into six families that map directly to the Open Metadata Types taxonomy areas: + +| # | Family | Key schemas | +|---|--------|-------------| +| 1 | **Physical Assets** | `Connector`, `PhysicalAsset` | +| 2 | **Glossary** | `GlossaryTerm`, `AuthorityLink` | +| 3 | **Governance** | `Policy`, `Rule`, `PolicyCondition`, `PolicyDecision`, `CapabilityToken`, `Obligation`, `Exception` | +| 4 | **Collaboration** | `Comment`, `Rating`, `Community` | +| 5 | **Models / Schemas** | `SchemaDefinition`, `EntityField`, `Field`, `ValidValues`, `TagAssignment`, `QualityMetric`, `ProfileStats` | +| 6 | **Agreements** | `Agreement`, `Party` | +| + | **Execution / Provenance** | `Dataset`, `RunRecord`, `WorkflowSpec`, `WorkflowNode`, `WorkflowEdge`, `WorkloadSpec`, `DataSphere`, `ProvenanceRecord`, `EventEnvelope`, `MappingSpec` | +| + | **Agent Plane** | `AgentSession`, `ExecutionDecision`, `ExecutionSurface`, `SkillManifest`, `MemoryEntry`, `SessionReceipt`, `SessionReview`, `TelemetryEvent`, `FrustrationSignal` | +| + | **Release / Experiments** | `ExperimentFlag`, `RolloutPolicy`, `ReleaseReceipt` | + +--- + +## Quick start + +### 1 — Validate a payload against a schema + +```bash +# Node.js (AJV) +npm install ajv ajv-formats +node -e " +const Ajv = require('ajv/dist/2020'); +const addFormats = require('ajv-formats'); +const schema = require('./schemas/Dataset.json'); +const example = require('./examples/dataset.json'); +const ajv = new Ajv(); addFormats(ajv); +const valid = ajv.validate(schema, example); +console.log(valid ? 'VALID' : ajv.errorsText()); +" + +# Python (jsonschema) +pip install jsonschema +python -c " +import json, jsonschema +schema = json.load(open('schemas/Dataset.json')) +example = json.load(open('examples/dataset.json')) +jsonschema.validate(example, schema) +print('VALID') +" +``` + +### 2 — Generate TypeScript types + +```bash +npm install -g quicktype +quicktype --src schemas/ --src-lang schema --lang typescript --out src/types/srcos.ts +``` + +### 3 — Generate Python Pydantic models + +```bash +pip install datamodel-code-generator +datamodel-codegen --input schemas/ --input-file-type jsonschema --output models/ +``` + +### 4 — Generate a FastAPI stub from the OpenAPI spec + +```bash +pip install fastapi-code-generator +fastapi-codegen --input openapi.yaml --output app/ +``` + +--- ## Compatibility discipline -- IDs are stable URNs; specVersion is semver. -- Additive changes should remain backward compatible; breaking changes increment major. + +- **IDs** are stable URNs of the form `urn:srcos::`. +- **`specVersion`** follows [Semantic Versioning](https://semver.org/): additive changes are minor bumps; breaking changes increment the major version. +- All breaking changes are recorded in [CHANGELOG.md](CHANGELOG.md) and accompanied by an ADR in [docs/adr/](docs/adr/). + +--- + +## Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md) for schema authoring conventions, the URN naming guide, and the pull-request checklist. diff --git a/docs/adr/0000-template.md b/docs/adr/0000-template.md new file mode 100644 index 0000000..3d076c6 --- /dev/null +++ b/docs/adr/0000-template.md @@ -0,0 +1,28 @@ +# ADR Template + +**Date:** YYYY-MM-DD +**Status:** `Proposed` | `Accepted` | `Deprecated` | `Superseded by ADR-NNNN` + +--- + +## Context + +Describe the problem or situation that requires a decision. Include relevant constraints and goals. + +## Decision + +State the decision clearly and concisely. + +## Alternatives considered + +| Alternative | Reason not chosen | +|-------------|------------------| +| ... | ... | + +## Consequences + +Describe the positive and negative consequences of this decision. + +## References + +- Link to relevant issues, PRs, or external documents diff --git a/docs/adr/0001-urn-identity-scheme.md b/docs/adr/0001-urn-identity-scheme.md new file mode 100644 index 0000000..708af35 --- /dev/null +++ b/docs/adr/0001-urn-identity-scheme.md @@ -0,0 +1,52 @@ +# ADR-0001: Use `urn:srcos:` as the universal identifier namespace + +**Date:** 2025-12-24 +**Status:** Accepted + +--- + +## Context + +Every object in the spec needs a stable, globally unique identifier that: +- Is collision-free across multiple deployments and organisations. +- Can be compared as a plain string without parsing. +- Embeds type information so a resolver can route to the right handler without a schema look-up. +- Follows an existing, well-understood standard. + +Several options were evaluated: +- UUID v4 (opaque, no type information, collision-free) +- HTTP URL (requires a resolvable server, fragile across environments) +- URN with custom NID (standards-compliant, type-aware, stable) + +## Decision + +All top-level objects use Uniform Resource Names of the form: + +``` +urn:srcos:: +``` + +The NID (Namespace Identifier) is `srcos` — a stable, project-specific NID registered in the spec. The NSS (Namespace Specific String) has a mandatory `` prefix so the type of object can be determined from the URN alone. + +## Alternatives considered + +| Alternative | Reason not chosen | +|-------------|------------------| +| UUID v4 | No embedded type information; resolving requires external registry | +| HTTP URL | Fragile — depends on server availability; breaks in air-gapped environments | +| `urn:sourceos:` (long form) | More verbose; abbreviation `srcos` is consistent with other project naming | + +## Consequences + +**Positive:** +- Identifiers are portable across environments and are self-describing. +- Pattern constraints in JSON Schema (e.g. `"pattern": "^urn:srcos:dataset:"`) provide type-safe cross-references validated at schema-validation time. +- No central registry required for local development. + +**Negative:** +- Local IDs are not globally unique without organisational prefix conventions; multi-tenant deployments must ensure their `local-id` space is scoped (e.g. include an org slug). + +## References + +- RFC 8141 – Uniform Resource Names (URNs) +- `ARCHITECTURE.md` §4 URN identity scheme diff --git a/docs/adr/0002-typed-policy-condition.md b/docs/adr/0002-typed-policy-condition.md new file mode 100644 index 0000000..3bbc4eb --- /dev/null +++ b/docs/adr/0002-typed-policy-condition.md @@ -0,0 +1,55 @@ +# ADR-0002: Typed `PolicyCondition` with declared expression language + +**Date:** 2025-12-24 +**Status:** Accepted + +--- + +## Context + +Version 1 policy rules used free-form JSON objects for conditions, with no declared language or evaluation semantics. This made it impossible to: +- Statically analyse policies for conflicts or completeness. +- Choose an appropriate evaluator without out-of-band configuration. +- Validate that expressions are syntactically correct for their language. + +The spec needed a way to embed policy conditions that is both machine-evaluable and auditable. + +## Decision + +`PolicyCondition` carries an explicit `language` discriminator field with four supported values: + +| Value | Language | Evaluator | +|-------|----------|-----------| +| `jsonlogic` | [JSON Logic](https://jsonlogic.com/) | Lightweight, embeddable, no external deps | +| `cel` | [Common Expression Language](https://cel.dev/) | Google Cloud, Kubernetes, Open Policy Agent | +| `rego` | [Open Policy Agent Rego](https://www.openpolicyagent.org/docs/latest/policy-language/) | Full policy-as-code system | +| `cedar` | [AWS Cedar](https://www.cedarpolicy.com/) | Purpose-built authorisation, strongly typed | + +The `expr` field holds the condition expression as an opaque JSON object whose structure is defined by the `language` value. + +## Alternatives considered + +| Alternative | Reason not chosen | +|-------------|------------------| +| Single language only (e.g. Rego) | Forces all deployments to run a full OPA sidecar; overkill for simple conditions | +| String expression (FEEL, SpEL) | Not natively embeddable in JSON without escaping; harder to statically analyse | +| No conditions (binary permit/deny) | Insufficient for real-world ABAC/PBAC requirements | + +## Consequences + +**Positive:** +- Implementations can choose the evaluator appropriate to their stack. +- `jsonlogic` covers the majority of simple conditions with zero external dependencies. +- The `language` field enables static routing to the correct evaluator without parsing the expression. +- Future languages can be added as new enum values (additive / minor version bump). + +**Negative:** +- Implementations must handle all four languages or document which subset they support. +- Cross-language policy sets cannot be uniformly evaluated by a single engine. +- Expression syntax is not validated by JSON Schema (only `expr: { type: object }`) — a linter or separate validator is required. + +## References + +- `schemas/PolicyCondition.json` +- `schemas/Rule.json` +- `examples/policy.json` — demonstrates `jsonlogic` condition diff --git a/docs/adr/0003-agent-plane-patch-files.md b/docs/adr/0003-agent-plane-patch-files.md new file mode 100644 index 0000000..dcc995b --- /dev/null +++ b/docs/adr/0003-agent-plane-patch-files.md @@ -0,0 +1,47 @@ +# ADR-0003: Additive patch files for the agent plane + +**Date:** 2025-12-24 +**Status:** Accepted + +--- + +## Context + +The SourceOS agent plane (agent sessions, execution decisions, skill manifests, memory) is a distinct concern from the metadata governance plane (datasets, policies, provenance). Not all deployments require the agent plane. Folding agent-plane endpoints into the single `openapi.yaml` and `asyncapi.yaml` would: +- Force all consumers to deal with agent-plane types even if they only use the metadata plane. +- Make the base spec harder to read and maintain. +- Couple the release cycle of both planes. + +## Decision + +The agent-plane OpenAPI endpoints are defined in a separate file, `openapi.agent-plane.patch.yaml`, and the agent-plane AsyncAPI channels in `asyncapi.agent-plane.patch.yaml`. + +Both patch files are **additive only** — they add new `paths` / `channels` without modifying or removing anything in the base spec. + +Consumers merge the patches at build time using standard tooling (`openapi-merge-cli`, `@asyncapi/bundler`). + +## Alternatives considered + +| Alternative | Reason not chosen | +|-------------|------------------| +| Separate standalone specs | Duplicates shared component schemas; two separate server surfaces to maintain | +| Single unified spec | Couples agent-plane and metadata-plane release cycles; harder to deploy metadata-only | +| OpenAPI overlays (v1 spec) | Standard not finalised at time of design; tooling immature | + +## Consequences + +**Positive:** +- Metadata-plane-only implementations carry zero agent-plane surface area. +- Each plane can evolve independently. +- The patch model is explicit and auditable — diffs are small and focused. + +**Negative:** +- Build pipelines must include a merge step. +- Tooling for patch merging is not yet standardised across all OpenAPI/AsyncAPI tools. +- Ordering matters — the base spec must be loaded before the patch. + +## References + +- `openapi.agent-plane.patch.yaml` +- `asyncapi.agent-plane.patch.yaml` +- `CONTRIBUTING.md` §Updating the API specs diff --git a/docs/adr/0004-json-schema-2020-12.md b/docs/adr/0004-json-schema-2020-12.md new file mode 100644 index 0000000..81427ee --- /dev/null +++ b/docs/adr/0004-json-schema-2020-12.md @@ -0,0 +1,42 @@ +# ADR-0004: JSON Schema draft 2020-12 as the schema language + +**Date:** 2025-12-24 +**Status:** Accepted + +--- + +## Context + +The spec requires a schema language that: +- Is widely supported by validators in multiple languages (Node.js, Python, Java, Go). +- Supports `$ref` for schema composition and cross-file references. +- Supports `additionalProperties: false` for strict object validation. +- Has a stable, versioned specification. + +## Decision + +All schemas use [JSON Schema draft 2020-12](https://json-schema.org/specification) (`"$schema": "https://json-schema.org/draft/2020-12/schema"`). + +## Alternatives considered + +| Alternative | Reason not chosen | +|-------------|------------------| +| JSON Schema draft-07 | Still widely supported, but lacks `prefixItems`, `unevaluatedProperties`, and updated `$ref` semantics | +| OpenAPI Schema Object | Dialect of JSON Schema with extensions; would couple schema files to OpenAPI tooling | +| Avro / Protobuf | Binary-oriented; poor fit for REST/JSON document exchange; requires schema registry | +| TypeSpec / Cadl | Microsoft-specific; limited ecosystem outside Azure | + +## Consequences + +**Positive:** +- AJV 8 (Node.js) and `jsonschema` 4 (Python) fully support draft 2020-12. +- `quicktype` and `datamodel-code-generator` can ingest the schemas directly. +- `$id` URIs are stable IRIs usable in JSON-LD contexts. + +**Negative:** +- Some older tools (e.g. older versions of `swagger-ui`) do not support draft 2020-12 `$schema` declarations — consumers may need to strip the `$schema` field when embedding schemas in OpenAPI components. + +## References + +- JSON Schema 2020-12 specification: https://json-schema.org/draft/2020-12/release-notes +- AJV support matrix: https://ajv.js.org/json-schema.html diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..3704712 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,115 @@ +# Examples + +This directory contains one conforming JSON example payload for each top-level schema type in the SourceOS/SociOS specification. + +--- + +## What the examples show + +The examples are designed to tell a coherent end-to-end story: a personal health dataset is catalogued, governed, transformed by an obfuscation workload, and released — all within an agent session. They share cross-reference URNs so you can trace the full lifecycle: + +``` +connector.json ──► asset.json + │ + ▼ + dataset.json ──► schema.json + │ │ + │ ▼ + │ field.json + │ + policy.json + │ + ▼ + decision.json ──► token.json + │ + ▼ + run.json ──► provenance.json + │ + ▼ + event.json + +glossary.json ◄── field.json (glossaryTerms) +mapping.json ──► dataset.json (from/to) +comment.json ──► mapping.json (targetId) +agreement.json ◄── dataset.json (governance.agreements) + +agentsession.json ──► executiondecision.json ──► sessionreceipt.json + │ + ▼ + sessionreview.json +``` + +--- + +## File index + +| File | Schema type | Description | +|------|------------|-------------| +| `agreement.json` | Agreement | Default personal-data agreement | +| `agentsession.json` | AgentSession | An executor session running the obfuscation workflow | +| `asset.json` | PhysicalAsset | Lakehouse asset for curated health observations | +| `capabilitytoken.json` | CapabilityToken | Access token scoped to the health dataset export operation | +| `comment.json` | Comment | A review note on a field mapping | +| `community.json` | Community | The data-governance team community | +| `connector.json` | Connector | A local S3 connector | +| `dataset.json` | Dataset | Personal health observations dataset | +| `datasphere.json` | DataSphere | The personal-curated execution environment | +| `decision.json` | PolicyDecision | An `export` permit decision with an obfuscation obligation | +| `executiondecision.json` | ExecutionDecision | Agent allow-decision for a tool invocation | +| `experimentflag.json` | ExperimentFlag | A feature flag for the new obfuscation algorithm | +| `event.json` | EventEnvelope | Event published when the run completes | +| `field.json` | Field | The `patient.dateOfBirth` field with PII tags and quality metrics | +| `frustration.json` | FrustrationSignal | A frustration signal from a repeated-failure condition | +| `glossary.json` | GlossaryTerm | Glossary term for "Date of Birth" | +| `mapping.json` | MappingSpec | A field mapping between two dataset fields | +| `memory.json` | MemoryEntry | A learned memory entry from an agent session | +| `policy.json` | Policy | Health export must be obfuscated | +| `provenance.json` | ProvenanceRecord | Provenance record for the obfuscation run | +| `rating.json` | Rating | A 5-star rating on the health observations dataset | +| `releasereceipt.json` | ReleaseReceipt | Release receipt for spec version 2.0.0 | +| `rolloutpolicy.json` | RolloutPolicy | Rollout rules for the obfuscation experiment flag | +| `run.json` | RunRecord | The obfuscation workload run record | +| `schema.json` | SchemaDefinition | The schema for health observations | +| `sessionreceipt.json` | SessionReceipt | Receipt for the completed agent session | +| `sessionreview.json` | SessionReview | Post-session learning review | +| `skillmanifest.json` | SkillManifest | The obfuscation skill manifest | +| `telemetry.json` | TelemetryEvent | An informational telemetry event from the agent session | +| `token.json` | CapabilityToken | Capability token for the export operation | +| `workflow.json` | WorkflowSpec | The health-data obfuscation workflow | + +--- + +## Validating examples + +```bash +# Install AJV CLI +npm install -g ajv-cli + +# Validate a single example +ajv validate -s ../schemas/Dataset.json -d dataset.json + +# Validate all examples +cd .. +for example in examples/*.json; do + name=$(basename "$example" .json) + # Find matching schema (PascalCase title) + python3 - <` - -### AgentSession URN -- **Pattern**: `urn:sourceos:agent:session:` - -### SessionReceipt URN -- **Pattern**: `urn:sourceos:receipt:` - -## Schema Metadata Explanation -Each schema includes metadata that describes its purpose, version, and last updated information. - -- **Version**: Indicates the version of the schema. -- **Last Updated**: Date when the schema was last modified. - -## Usage Examples -### ExecutionDecision Example -```json -{ - "id": "urn:sourceos:execution:decision:12345", - "metadata": { - "version": "1.0", - "lastUpdated": "2026-04-05" - }, - "decision": "approve" -} -``` +# Schema Catalog -### AgentSession Example -```json -{ - "id": "urn:sourceos:agent:session:12345", - "metadata": { - "version": "1.0", - "lastUpdated": "2026-04-05" - }, - "status": "active" -} -``` +This directory contains all 54 JSON Schema (draft 2020-12) files that make up the SourceOS/SociOS Typed Contracts specification. -### SessionReceipt Example -```json -{ - "id": "urn:sourceos:receipt:12345", - "metadata": { - "version": "1.0", - "lastUpdated": "2026-04-05" - }, - "result": "success" -} -``` +--- + +## Quick reference + +| File | Type | URN prefix | +|------|------|-----------| +| `AgentSession.json` | AgentSession | `urn:srcos:session:` | +| `Agreement.json` | Agreement | `urn:srcos:agreement:` | +| `AuthorityLink.json` | AuthorityLink | _(sub-object, no top-level id)_ | +| `CapabilityToken.json` | CapabilityToken | _(plain `tokenId` string)_ | +| `Comment.json` | Comment | `urn:srcos:comment:` | +| `Community.json` | Community | `urn:srcos:community:` | +| `Connector.json` | Connector | `urn:srcos:connector:` | +| `DataRef.json` | DataRef | _(sub-object, no top-level id)_ | +| `DataSphere.json` | DataSphere | `urn:srcos:sphere:` | +| `Dataset.json` | Dataset | `urn:srcos:dataset:` | +| `EntityField.json` | EntityField | _(sub-object inside SchemaDefinition)_ | +| `EventEnvelope.json` | EventEnvelope | `urn:srcos:event:` | +| `Exception.json` | Exception | _(sub-object inside Policy)_ | +| `ExecutionDecision.json` | ExecutionDecision | `urn:srcos:exec-decision:` | +| `ExecutionSurface.json` | ExecutionSurface | _(sub-object inside AgentSession)_ | +| `ExperimentFlag.json` | ExperimentFlag | `urn:srcos:flag:` | +| `Field.json` | Field | `urn:srcos:field:` | +| `FrustrationSignal.json` | FrustrationSignal | `urn:srcos:frustration:` | +| `GlossaryTerm.json` | GlossaryTerm | `urn:srcos:glossary:` | +| `Link.json` | Link | _(sub-object, no id)_ | +| `MappingEvidence.json` | MappingEvidence | _(sub-object inside MappingSpec)_ | +| `MappingSpec.json` | MappingSpec | `urn:srcos:mapping:` | +| `MemoryEntry.json` | MemoryEntry | `urn:srcos:memory:` | +| `ObjectContext.json` | ObjectContext | _(sub-object, no id)_ | +| `ObjectSelector.json` | ObjectSelector | _(sub-object inside Policy scope)_ | +| `Obligation.json` | Obligation | _(sub-object, no id)_ | +| `Party.json` | Party | `urn:srcos:party:` | +| `PhysicalAsset.json` | PhysicalAsset | `urn:srcos:asset:` | +| `Policy.json` | Policy | `urn:srcos:policy:` | +| `PolicyBinding.json` | PolicyBinding | _(sub-object inside WorkflowSpec)_ | +| `PolicyCondition.json` | PolicyCondition | _(sub-object inside Rule)_ | +| `PolicyDecision.json` | PolicyDecision | `urn:srcos:decision:` | +| `ProfileStats.json` | ProfileStats | _(sub-object inside Field.quality)_ | +| `ProvenanceRecord.json` | ProvenanceRecord | `urn:srcos:prov:` | +| `QualityMetric.json` | QualityMetric | _(sub-object inside Field.quality)_ | +| `Rating.json` | Rating | `urn:srcos:rating:` | +| `ReleaseReceipt.json` | ReleaseReceipt | `urn:srcos:release-receipt:` | +| `RolloutPolicy.json` | RolloutPolicy | `urn:srcos:rollout:` | +| `Rule.json` | Rule | _(sub-object inside Policy)_ | +| `RunRecord.json` | RunRecord | `urn:srcos:run:` | +| `SchemaDefinition.json` | SchemaDefinition | `urn:srcos:schema:` | +| `SessionReceipt.json` | SessionReceipt | `urn:srcos:receipt:session:` | +| `SessionReview.json` | SessionReview | `urn:srcos:session-review:` | +| `SkillManifest.json` | SkillManifest | `urn:srcos:skill:` | +| `SubjectContext.json` | SubjectContext | _(sub-object, no id)_ | +| `SubjectSelector.json` | SubjectSelector | _(sub-object inside Policy scope)_ | +| `TagAssignment.json` | TagAssignment | _(sub-object inside Field/GlossaryTerm)_ | +| `TelemetryEvent.json` | TelemetryEvent | `urn:srcos:telemetry:` | +| `Trigger.json` | Trigger | _(sub-object inside WorkflowSpec)_ | +| `ValidValues.json` | ValidValues | _(sub-object inside EntityField)_ | +| `WorkflowEdge.json` | WorkflowEdge | _(sub-object inside WorkflowSpec)_ | +| `WorkflowNode.json` | WorkflowNode | _(sub-object inside WorkflowSpec)_ | +| `WorkflowSpec.json` | WorkflowSpec | `urn:srcos:workflow:` | +| `WorkloadSpec.json` | WorkloadSpec | `urn:srcos:workload:` | + +--- + +## Schema families + +### Family 1 – Physical Assets + +| Schema | Description | +|--------|-------------| +| `Connector` | A named, typed connection to a physical data store (S3, GCS, RDBMS, Kafka, …) | +| `PhysicalAsset` | A specific resource (table, bucket prefix, topic) reachable via a `Connector` | + +### Family 2 – Glossary + +| Schema | Description | +|--------|-------------| +| `GlossaryTerm` | A defined business term with synonyms, tags, and authority links | +| `AuthorityLink` | A pointer to an external controlled vocabulary entry (SNOMED, ISO, internal wiki) | + +### Family 3 – Governance + +| Schema | Description | +|--------|-------------| +| `Policy` | An access policy with subject/object/purpose scope, rules, obligations, and exceptions | +| `Rule` | A single `permit`/`deny` rule with an optional typed condition | +| `PolicyCondition` | A rule expression in `jsonlogic`, `cel`, `rego`, or `cedar` | +| `SubjectSelector` | A subject match clause in a Policy scope | +| `ObjectSelector` | An object match clause in a Policy scope | +| `PolicyDecision` | The immutable audit record of a `/v2/decisions/evaluate` call | +| `CapabilityToken` | A short-lived, signed access grant derived from a `PolicyDecision` | +| `Obligation` | A required action (`pre`/`post`/`runtime`) attached to a policy decision or token | +| `Exception` | A time-limited exemption from a Policy rule | +| `PolicyBinding` | Associates a Policy with a WorkflowSpec or SkillManifest | + +### Family 4 – Collaboration + +| Schema | Description | +|--------|-------------| +| `Comment` | A free-text annotation on any addressable object | +| `Rating` | A 1–5 star rating on any addressable object | +| `Community` | A named group of subject URNs | -## Validation Instructions -Schema validation must be performed against the JSON Schema specification outlined in the [official documentation](https://json-schema.org/). +### Family 5 – Models / Schemas + +| Schema | Description | +|--------|-------------| +| `SchemaDefinition` | A named, versioned logical schema composed of `EntityField`s | +| `EntityField` | A field descriptor inside a `SchemaDefinition` | +| `Field` | A fully annotated, quality-profiled field attached to a live `Dataset` | +| `TagAssignment` | A classification tag with confidence score, source, and review record | +| `ValidValues` | Enumeration, numeric range, or regex constraint on a field | +| `QualityMetric` | A named quality dimension (completeness, validity, …) scored 0–1 | +| `ProfileStats` | Statistical profile of a column: row count, nulls, distinct values, top-N values | + +### Family 6 – Agreements + +| Schema | Description | +|--------|-------------| +| `Agreement` | A data-sharing agreement between one or more parties with terms and effective dates | +| `Party` | A named signatory (person, org, or service) with optional authority links | + +### Execution / Provenance + +| Schema | Description | +|--------|-------------| +| `Dataset` | A logical view of a `PhysicalAsset` with governance, schema, and lifecycle metadata | +| `DataRef` | A typed pointer to a dataset, asset, stream topic, or file | +| `DataSphere` | A bounded execution environment with zone, network, and storage controls | +| `WorkloadSpec` | A container, Spark job, function, or stream processor specification | +| `RunRecord` | The audit record of a single workload execution | +| `WorkflowSpec` | A DAG of `WorkflowNode`s connected by `WorkflowEdge`s | +| `WorkflowNode` | A single processing node in a `WorkflowSpec` | +| `WorkflowEdge` | A directed dependency edge between two `WorkflowNode` IDs | +| `Trigger` | How a workflow is activated: cron schedule, event, or manual | +| `ProvenanceRecord` | A W3C PROV-compatible record linking a run to its input/output entities | +| `MappingSpec` | A field-to-field semantic mapping with multi-method confidence evidence | +| `MappingEvidence` | A single evidence item for a `MappingSpec` (label similarity, value overlap, …) | +| `EventEnvelope` | The universal wrapper for all AsyncAPI channel messages | + +### Agent Plane + +| Schema | Description | +|--------|-------------| +| `AgentSession` | A single autonomous agent session with role, mode, substrate, and execution surface | +| `ExecutionSurface` | Sandboxing, network, and filesystem constraints for an agent's environment | +| `ExecutionDecision` | An immutable record of an agent's allow/deny/ask/defer/rewrite decision | +| `SkillManifest` | A declared agent skill with activation rules, requirements, and policy bindings | +| `MemoryEntry` | A persistent agent memory of kind `rule`, `learned`, or `recap` | +| `SessionReceipt` | The final outcome record for a completed `AgentSession` | +| `SessionReview` | A post-session learning review linking to extracted memory entries | +| `TelemetryEvent` | A structured log event emitted during an agent session | +| `FrustrationSignal` | A behavioural signal indicating agent or user difficulty | + +### Release / Experiments + +| Schema | Description | +|--------|-------------| +| `ExperimentFlag` | A feature flag with lifecycle: off → shadow → internal → beta → on → retired | +| `RolloutPolicy` | Audience-based percentage rollout rules for an `ExperimentFlag` | +| `ReleaseReceipt` | A verified release record with artifact hashes and gate check results | + +--- + +## Validation + +```bash +# Validate a single example against its schema +npx ajv-cli validate -s AgentSession.json -d ../examples/agentsession.json + +# Validate all examples in bulk +for schema in *.json; do + type=$(python3 -c "import json; d=json.load(open('$schema')); print(d.get('title',''))") + example="../examples/$(echo $type | tr '[:upper:]' '[:lower:]').json" + [ -f "$example" ] && npx ajv-cli validate -s "$schema" -d "$example" && echo "✓ $type" +done +``` -## Versioning Discipline -Follow semantic versioning for all schema updates: -- Major version when incompatible API changes are made, -- Minor version when functionality is added in a backward-compatible manner, -- Patch version when backward-compatible bug fixes are introduced. +--- -## Current Status -All schemas are currently under active development. All feedback is welcomed. +## Versioning -## References -- [JSON Schema Official Website](https://json-schema.org/) -- SourceOS Documentation -- API Reference links \ No newline at end of file +Schema evolution follows [Semantic Versioning](https://semver.org/). See [CONTRIBUTING.md](../CONTRIBUTING.md#breaking-vs-additive-changes) for the full policy and [CHANGELOG.md](../CHANGELOG.md) for the history. diff --git a/semantic/README.md b/semantic/README.md new file mode 100644 index 0000000..37642c9 --- /dev/null +++ b/semantic/README.md @@ -0,0 +1,95 @@ +# Semantic Overlay + +This directory provides the JSON-LD and Hydra semantic overlay for the SourceOS/SociOS specification. These files make the schema types and REST API self-describing to Linked Data tooling. + +--- + +## Files + +| File | Purpose | +|------|---------| +| `context.jsonld` | JSON-LD `@context` mapping all 54 schema type names to stable IRIs under `https://schemas.srcos.ai/v2/` | +| `hydra.jsonld` | A `hydra:ApiDocumentation` document describing the REST API's supported classes and operations | + +--- + +## `context.jsonld` — JSON-LD context + +Include the context in any JSON document to make it a JSON-LD document: + +```json +{ + "@context": "https://schemas.srcos.ai/v2/context.jsonld", + "@type": "Dataset", + "id": "urn:srcos:dataset:health_obs", + ... +} +``` + +Or embed the context inline: + +```json +{ + "@context": { + "srcos": "https://schemas.srcos.ai/v2/", + "Dataset": "srcos:Dataset" + } +} +``` + +The context maps: +- `id` → `@id` (every `id` field becomes the node's IRI) +- `type` → `@type` (every `type` field becomes the node's RDF type) +- All 54 schema type names to `srcos:` IRIs +- Selected cross-vocabulary terms: `prov:wasGeneratedBy`, `prov:used`, `prov:wasAssociatedWith` + +--- + +## `hydra.jsonld` — Hydra API documentation + +The Hydra document is a machine-readable API description that extends the JSON-LD context. It can be served at `/.well-known/hydra` to make the API self-describing. + +The document lists every resource class supported by the API with its supported operations (HTTP methods), expected inputs, and returned types. + +--- + +## Usage with Linked Data tools + +### Validate JSON-LD framing + +```bash +npm install -g jsonld-cli +jsonld frame --frame '{"@type":"Dataset"}' examples/dataset.json +``` + +### Generate RDF/Turtle from an example + +```bash +jsonld format --output-format nquads examples/dataset.json +``` + +### Check Hydra documentation + +```bash +curl https://api.srcos.local/.well-known/hydra | python3 -m json.tool +``` + +--- + +## Extending the context + +When adding a new first-class schema type: + +1. Add a mapping to `context.jsonld`: `"NewType": "srcos:NewType"` +2. Add a `hydra:supportedClass` entry to `hydra.jsonld` with at minimum `hydra:title`, `hydra:description`, and the applicable `hydra:supportedOperation` entries. +3. Update this README's file table. + +See [CONTRIBUTING.md](../CONTRIBUTING.md#6-update-the-semantic-context-if-needed) for the full guide. + +--- + +## Standards references + +- [JSON-LD 1.1](https://www.w3.org/TR/json-ld11/) +- [Hydra Core Vocabulary](https://www.hydra-cg.com/spec/latest/core/) +- [W3C PROV-O](https://www.w3.org/TR/prov-o/) — used for `ProvenanceRecord` mappings From 94949ecf0e2c468a33712b7b08a15dd13958e73f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 17:21:10 +0000 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20Phase=202+3=20=E2=80=93=20annotate?= =?UTF-8?q?=20all=2054=20schemas=20and=20improve=20OpenAPI/AsyncAPI=20spec?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agent-Logs-Url: https://github.com/SourceOS-Linux/sourceos-spec/sessions/8b9ff02b-0b12-4bf8-8f38-efe8f63363c9 Co-authored-by: mdheller <21163552+mdheller@users.noreply.github.com> --- asyncapi.agent-plane.patch.yaml | 129 ++++++++++- asyncapi.yaml | 147 ++++++++++++ openapi.agent-plane.patch.yaml | 86 ++++++- openapi.yaml | 384 ++++++++++++++++++++++++++++++-- schemas/AgentSession.json | 55 +++-- schemas/Agreement.json | 30 ++- schemas/AuthorityLink.json | 12 +- schemas/CapabilityToken.json | 30 ++- schemas/Comment.json | 24 +- schemas/Community.json | 24 +- schemas/Connector.json | 24 +- schemas/DataRef.json | 12 +- schemas/DataSphere.json | 15 +- schemas/Dataset.json | 33 ++- schemas/EntityField.json | 21 +- schemas/EventEnvelope.json | 27 ++- schemas/Exception.json | 12 +- schemas/ExecutionDecision.json | 40 ++-- schemas/ExecutionSurface.json | 34 ++- schemas/ExperimentFlag.json | 63 +++++- schemas/Field.json | 30 ++- schemas/FrustrationSignal.json | 58 ++++- schemas/GlossaryTerm.json | 33 ++- schemas/Link.json | 12 +- schemas/MappingEvidence.json | 15 +- schemas/MappingSpec.json | 27 ++- schemas/MemoryEntry.json | 34 ++- schemas/ObjectContext.json | 18 +- schemas/ObjectSelector.json | 9 +- schemas/Obligation.json | 12 +- schemas/Party.json | 15 +- schemas/PhysicalAsset.json | 24 +- schemas/Policy.json | 27 ++- schemas/PolicyBinding.json | 9 +- schemas/PolicyCondition.json | 12 +- schemas/PolicyDecision.json | 33 ++- schemas/ProfileStats.json | 24 +- schemas/ProvenanceRecord.json | 21 +- schemas/QualityMetric.json | 12 +- schemas/Rating.json | 24 +- schemas/ReleaseReceipt.json | 70 +++++- schemas/RolloutPolicy.json | 70 +++++- schemas/Rule.json | 12 +- schemas/RunRecord.json | 42 ++-- schemas/SchemaDefinition.json | 24 +- schemas/SessionReceipt.json | 28 ++- schemas/SessionReview.json | 51 ++++- schemas/SkillManifest.json | 46 ++-- schemas/SubjectContext.json | 15 +- schemas/SubjectSelector.json | 9 +- schemas/TagAssignment.json | 21 +- schemas/TelemetryEvent.json | 53 ++++- schemas/Trigger.json | 12 +- schemas/ValidValues.json | 18 +- schemas/WorkflowEdge.json | 9 +- schemas/WorkflowNode.json | 21 +- schemas/WorkflowSpec.json | 27 ++- schemas/WorkloadSpec.json | 18 +- 58 files changed, 1756 insertions(+), 441 deletions(-) diff --git a/asyncapi.agent-plane.patch.yaml b/asyncapi.agent-plane.patch.yaml index 8e7f200..a3d3cc7 100644 --- a/asyncapi.agent-plane.patch.yaml +++ b/asyncapi.agent-plane.patch.yaml @@ -1,27 +1,154 @@ -# additive AsyncAPI patch fragment for the core agent-plane schema family +# Additive AsyncAPI patch fragment for the agent-plane schema family. +# Merge this file into asyncapi.yaml at build time using @asyncapi/bundler. +# All channels use Kafka with the same broker configuration as the base spec. + channels: srcos.v2.session.events: + description: Events emitted when an AgentSession is created, updated, or reaches a terminal state. + bindings: + kafka: + topic: srcos.v2.session.events + partitions: 6 + replicas: 3 + topicConfiguration: + retention.ms: 2592000000 + cleanup.policy: delete publish: + operationId: publishSessionEvent + summary: Publish an agent session domain event + description: Publishes an event when an AgentSession's state changes or a SessionReceipt is recorded. message: name: SessionEvent + title: Agent Session Domain Event + summary: A lifecycle event for an AgentSession or SessionReceipt. + description: | + The `eventType` in the payload envelope identifies the specific change: + - `AgentSessionStarted` — a new AgentSession was created with status "running" + - `AgentSessionCompleted` — an AgentSession reached a terminal status + - `SessionReceiptRecorded` — a SessionReceipt was persisted for a completed session + contentType: application/json payload: { $ref: './schemas/EventEnvelope.json' } + bindings: + kafka: + key: + type: string + description: The `objectId` URN of the affected AgentSession. + srcos.v2.execution.events: + description: Events emitted when an ExecutionDecision is recorded by an agent session. + bindings: + kafka: + topic: srcos.v2.execution.events + partitions: 3 + replicas: 3 + topicConfiguration: + retention.ms: 2592000000 + cleanup.policy: delete publish: + operationId: publishExecutionEvent + summary: Publish an execution decision event + description: Publishes an event whenever an agent records an ExecutionDecision (allow, deny, ask, defer, or rewrite). message: name: ExecutionEvent + title: Execution Decision Domain Event + summary: An immutable event for a recorded ExecutionDecision. + description: | + The `eventType` in the payload envelope is always `ExecutionDecisionRecorded`. + The payload contains the full ExecutionDecision object. + contentType: application/json payload: { $ref: './schemas/EventEnvelope.json' } + bindings: + kafka: + key: + type: string + description: The `objectId` URN of the ExecutionDecision. + srcos.v2.skill.events: + description: Events emitted when a SkillManifest is registered or updated. + bindings: + kafka: + topic: srcos.v2.skill.events + partitions: 3 + replicas: 3 + topicConfiguration: + retention.ms: 604800000 + cleanup.policy: delete publish: + operationId: publishSkillEvent + summary: Publish a skill manifest domain event + description: Publishes an event whenever a SkillManifest is created or updated. message: name: SkillEvent + title: Skill Manifest Domain Event + summary: A change event for a SkillManifest. + description: | + The `eventType` in the payload envelope is `SkillManifestUpserted`. + The payload contains the full SkillManifest object. + contentType: application/json payload: { $ref: './schemas/EventEnvelope.json' } + bindings: + kafka: + key: + type: string + description: The `objectId` URN of the SkillManifest. + srcos.v2.memory.events: + description: Events emitted when a MemoryEntry is created, updated, or reviewed. + bindings: + kafka: + topic: srcos.v2.memory.events + partitions: 3 + replicas: 3 + topicConfiguration: + retention.ms: 604800000 + cleanup.policy: delete publish: + operationId: publishMemoryEvent + summary: Publish a memory entry domain event + description: Publishes an event when a MemoryEntry is upserted or a SessionReview extracts new memories. message: name: MemoryEvent + title: Memory Entry Domain Event + summary: A lifecycle event for a MemoryEntry or SessionReview. + description: | + The `eventType` in the payload envelope identifies the specific change: + - `MemoryEntryUpserted` — a MemoryEntry was created or updated + - `SessionReviewCompleted` — a SessionReview was recorded with learned memory refs + contentType: application/json payload: { $ref: './schemas/EventEnvelope.json' } + bindings: + kafka: + key: + type: string + description: The `objectId` URN of the MemoryEntry or SessionReview. + srcos.v2.receipt.events: + description: Events emitted when a ReleaseReceipt is verified or fails. + bindings: + kafka: + topic: srcos.v2.receipt.events + partitions: 3 + replicas: 3 + topicConfiguration: + retention.ms: 2592000000 + cleanup.policy: delete publish: + operationId: publishReceiptEvent + summary: Publish a release receipt event + description: Publishes an event when a ReleaseReceipt is recorded after a deployment verification. message: name: ReceiptEvent + title: Release Receipt Domain Event + summary: A verification event for a ReleaseReceipt. + description: | + The `eventType` in the payload envelope identifies the outcome: + - `ReleaseVerified` — all gate checks passed and the release is verified + - `ReleaseFailed` — one or more gate checks failed + contentType: application/json payload: { $ref: './schemas/EventEnvelope.json' } + bindings: + kafka: + key: + type: string + description: The `objectId` URN of the ReleaseReceipt. + diff --git a/asyncapi.yaml b/asyncapi.yaml index 27cba6e..743a787 100644 --- a/asyncapi.yaml +++ b/asyncapi.yaml @@ -2,29 +2,176 @@ asyncapi: 2.6.0 info: title: SourceOS/SociOS Event Spine version: 2.0.0 + description: | + The SourceOS/SociOS Event Spine carries domain events from the metadata governance plane. + All messages use the EventEnvelope schema as their payload wrapper. The `eventType` field + inside the envelope identifies the domain event (e.g. "DatasetUpserted", "PolicyEvaluated"). + + Consumers should subscribe to only the channels relevant to their domain. + All channels use Kafka as the default broker. + +servers: + development: + url: kafka://localhost:9092 + protocol: kafka + description: Local Kafka broker for development and testing. + production: + url: kafka://kafka.srcos.internal:9092 + protocol: kafka + description: Production Kafka cluster. + +defaultContentType: application/json + channels: srcos.v2.dataset.events: + description: Events emitted when a Dataset, Field, SchemaDefinition, or PhysicalAsset is created or updated. + bindings: + kafka: + topic: srcos.v2.dataset.events + partitions: 6 + replicas: 3 + topicConfiguration: + retention.ms: 604800000 + cleanup.policy: delete publish: + operationId: publishDatasetEvent + summary: Publish a dataset domain event + description: Publishes an event whenever a Dataset, Field, SchemaDefinition, or PhysicalAsset changes state. message: name: DatasetEvent + title: Dataset Domain Event + summary: A change event for a Dataset, Field, SchemaDefinition, or PhysicalAsset. + description: | + The `eventType` in the payload envelope identifies the specific change: + - `DatasetUpserted` — a Dataset was created or updated + - `FieldUpserted` — a Field was created or updated + - `SchemaDefinitionUpserted` — a SchemaDefinition was created or updated + - `PhysicalAssetUpserted` — a PhysicalAsset was created or updated + contentType: application/json payload: { $ref: './schemas/EventEnvelope.json' } + bindings: + kafka: + key: + type: string + description: The `objectId` URN of the affected entity, used as the Kafka message key for partition co-location. + srcos.v2.policy.events: + description: Events emitted when a Policy is created or updated, or when a PolicyDecision is recorded. + bindings: + kafka: + topic: srcos.v2.policy.events + partitions: 3 + replicas: 3 + topicConfiguration: + retention.ms: 2592000000 + cleanup.policy: delete publish: + operationId: publishPolicyEvent + summary: Publish a policy domain event + description: Publishes an event whenever a Policy is upserted or a PolicyDecision is evaluated. message: name: PolicyEvent + title: Policy Domain Event + summary: A change event for a Policy or PolicyDecision. + description: | + The `eventType` in the payload envelope identifies the specific change: + - `PolicyUpserted` — a Policy was created or updated + - `PolicyDecisionRecorded` — a PolicyDecision was evaluated and persisted + - `CapabilityTokenIssued` — a CapabilityToken was issued + contentType: application/json payload: { $ref: './schemas/EventEnvelope.json' } + bindings: + kafka: + key: + type: string + description: The `objectId` URN of the affected Policy or PolicyDecision. + srcos.v2.run.events: + description: Events emitted when a RunRecord or ProvenanceRecord is persisted. + bindings: + kafka: + topic: srcos.v2.run.events + partitions: 6 + replicas: 3 + topicConfiguration: + retention.ms: 2592000000 + cleanup.policy: delete publish: + operationId: publishRunEvent + summary: Publish a run domain event + description: Publishes an event when a workload run completes or provenance is captured. message: name: RunEvent + title: Run Domain Event + summary: A completion event for a RunRecord or ProvenanceRecord. + description: | + The `eventType` in the payload envelope identifies the specific change: + - `RunRecorded` — a RunRecord was persisted + - `ProvenanceRecorded` — a ProvenanceRecord was persisted + contentType: application/json payload: { $ref: './schemas/EventEnvelope.json' } + bindings: + kafka: + key: + type: string + description: The `objectId` URN of the RunRecord or ProvenanceRecord. + srcos.v2.mapping.events: + description: Events emitted when a MappingSpec is created, updated, or its state changes. + bindings: + kafka: + topic: srcos.v2.mapping.events + partitions: 3 + replicas: 3 + topicConfiguration: + retention.ms: 604800000 + cleanup.policy: delete publish: + operationId: publishMappingEvent + summary: Publish a mapping domain event + description: Publishes an event whenever a MappingSpec is upserted or its review state changes. message: name: MappingEvent + title: Mapping Domain Event + summary: A change event for a MappingSpec. + description: | + The `eventType` in the payload envelope identifies the specific change: + - `MappingUpserted` — a MappingSpec was created or updated + - `MappingStateChanged` — a MappingSpec state changed (proposed → curated, rejected) + contentType: application/json payload: { $ref: './schemas/EventEnvelope.json' } + bindings: + kafka: + key: + type: string + description: The `objectId` URN of the affected MappingSpec. + srcos.v2.glossary.events: + description: Events emitted when a GlossaryTerm is created or updated. + bindings: + kafka: + topic: srcos.v2.glossary.events + partitions: 3 + replicas: 3 + topicConfiguration: + retention.ms: 604800000 + cleanup.policy: delete publish: + operationId: publishGlossaryEvent + summary: Publish a glossary domain event + description: Publishes an event whenever a GlossaryTerm is upserted. message: name: GlossaryEvent + title: Glossary Domain Event + summary: A change event for a GlossaryTerm. + description: | + The `eventType` in the payload envelope identifies the specific change: + - `GlossaryTermUpserted` — a GlossaryTerm was created or updated + contentType: application/json payload: { $ref: './schemas/EventEnvelope.json' } + bindings: + kafka: + key: + type: string + description: The `objectId` URN of the affected GlossaryTerm. + diff --git a/openapi.agent-plane.patch.yaml b/openapi.agent-plane.patch.yaml index b4cdf8c..5b40cb5 100644 --- a/openapi.agent-plane.patch.yaml +++ b/openapi.agent-plane.patch.yaml @@ -1,18 +1,44 @@ -# additive OpenAPI patch fragment for the core agent-plane schema family +# Additive OpenAPI patch fragment for the agent-plane schema family. +# Merge this file into openapi.yaml at build time. +# All operations require bearerAuth (inherited from the base spec security requirement). + +tags: + - name: Agent Plane + description: Agent sessions, execution decisions, skills, memory, and session receipts + paths: /v2/sessions: post: operationId: upsertAgentSession + summary: Upsert an AgentSession + description: Creates or updates an autonomous agent session record with its role, mode, substrate, and execution surface. Idempotent on `id`. + tags: [Agent Plane] requestBody: required: true content: application/json: schema: { $ref: './schemas/AgentSession.json' } responses: - '200': { description: ok } + '200': + description: AgentSession created or updated successfully. + '400': + description: Request body is malformed JSON. + '401': + description: Missing or invalid authentication token. + '403': + description: Authenticated subject is not permitted to upsert sessions. + '422': + description: Request body is valid JSON but fails schema validation. + /v2/execution/decide: post: operationId: decideExecution + summary: Record an ExecutionDecision + description: | + Persists an immutable execution decision (allow, deny, ask, defer, or rewrite) made by + an agent during a session. Returns the stored ExecutionDecision with its assigned URN. + Idempotent on `id`. + tags: [Agent Plane] requestBody: required: true content: @@ -20,37 +46,85 @@ paths: schema: { $ref: './schemas/ExecutionDecision.json' } responses: '200': - description: execution decision + description: ExecutionDecision recorded and returned. content: application/json: schema: { $ref: './schemas/ExecutionDecision.json' } + '400': + description: Request body is malformed JSON. + '401': + description: Missing or invalid authentication token. + '403': + description: Authenticated subject is not permitted to record execution decisions. + '422': + description: Request body is valid JSON but fails schema validation. + /v2/skills: post: operationId: upsertSkillManifest + summary: Upsert a SkillManifest + description: Creates or updates an agent skill manifest with its activation rules, requirements, and policy bindings. Idempotent on `id`. + tags: [Agent Plane] requestBody: required: true content: application/json: schema: { $ref: './schemas/SkillManifest.json' } responses: - '200': { description: ok } + '200': + description: SkillManifest created or updated successfully. + '400': + description: Request body is malformed JSON. + '401': + description: Missing or invalid authentication token. + '403': + description: Authenticated subject is not permitted to upsert skill manifests. + '422': + description: Request body is valid JSON but fails schema validation. + /v2/memory: post: operationId: upsertMemoryEntry + summary: Upsert a MemoryEntry + description: Creates or updates a persistent agent memory entry of kind rule, learned, or recap. Idempotent on `id`. + tags: [Agent Plane] requestBody: required: true content: application/json: schema: { $ref: './schemas/MemoryEntry.json' } responses: - '200': { description: ok } + '200': + description: MemoryEntry created or updated successfully. + '400': + description: Request body is malformed JSON. + '401': + description: Missing or invalid authentication token. + '403': + description: Authenticated subject is not permitted to upsert memory entries. + '422': + description: Request body is valid JSON but fails schema validation. + /v2/receipts/session: post: operationId: recordSessionReceipt + summary: Record a SessionReceipt + description: Persists the final outcome record for a completed AgentSession, including all produced artifacts and gate results. Idempotent on `id`. + tags: [Agent Plane] requestBody: required: true content: application/json: schema: { $ref: './schemas/SessionReceipt.json' } responses: - '200': { description: ok } + '200': + description: SessionReceipt recorded successfully. + '400': + description: Request body is malformed JSON. + '401': + description: Missing or invalid authentication token. + '403': + description: Authenticated subject is not permitted to record session receipts. + '422': + description: Request body is valid JSON but fails schema validation. + diff --git a/openapi.yaml b/openapi.yaml index 0d64a9d..8ad1c03 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -2,181 +2,525 @@ openapi: 3.0.3 info: title: SourceOS/SociOS Metadata Plane API version: 2.0.0 + description: | + The SourceOS/SociOS Metadata Plane API provides REST endpoints for cataloguing physical + assets, managing datasets and schemas, evaluating access policies, issuing capability + tokens, recording workflow runs, capturing provenance, and supporting collaboration. + + All request and response bodies are JSON. All identifiers are stable URNs of the form + `urn:srcos::`. + + ## Authentication + All endpoints require a Bearer token in the `Authorization` header. + + ## Error format + Error responses use a standard `{ "code": "...", "message": "...", "details": [...] }` + envelope defined in the `Error` component schema. + servers: - url: https://api.srcos.local + description: Local development server + +tags: + - name: Physical Assets + description: Connectors and physical data store assets + - name: Metadata + description: Datasets, schemas, fields, glossary, and field mappings + - name: Governance + description: Policies, decisions, and capability tokens + - name: Execution + description: Workflows, runs, and provenance records + - name: Collaboration + description: Comments and ratings + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: JWT or opaque bearer token issued by the SourceOS identity service. + schemas: + Error: + type: object + description: Standard error response envelope. + required: [code, message] + properties: + code: + type: string + description: Machine-readable error code (e.g. "validation_error", "not_found"). + message: + type: string + description: Human-readable error message. + details: + type: array + description: Optional list of field-level error details. + items: + type: object + additionalProperties: true + +security: + - bearerAuth: [] + paths: /v2/connectors: post: operationId: upsertConnector + summary: Upsert a Connector + description: Creates or updates a named connection configuration for a physical data store. Idempotent on `id`. + tags: [Physical Assets] requestBody: required: true content: application/json: schema: { $ref: './schemas/Connector.json' } responses: - '200': { description: ok } + '200': + description: Connector created or updated successfully. + '400': + description: Request body is malformed JSON. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '401': + description: Missing or invalid authentication token. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '403': + description: Authenticated subject is not permitted to upsert connectors. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '422': + description: Request body is valid JSON but fails schema validation. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + /v2/assets: post: operationId: upsertPhysicalAsset + summary: Upsert a PhysicalAsset + description: Creates or updates a physical resource record that references a Connector. Idempotent on `id`. + tags: [Physical Assets] requestBody: required: true content: application/json: schema: { $ref: './schemas/PhysicalAsset.json' } responses: - '200': { description: ok } + '200': + description: PhysicalAsset created or updated successfully. + '400': + description: Request body is malformed JSON. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '401': + description: Missing or invalid authentication token. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '403': + description: Authenticated subject is not permitted to upsert assets. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '422': + description: Request body is valid JSON but fails schema validation. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + /v2/schemas: post: operationId: upsertSchemaDefinition + summary: Upsert a SchemaDefinition + description: Creates or updates a logical schema composed of EntityFields. Idempotent on `id`. + tags: [Metadata] requestBody: required: true content: application/json: schema: { $ref: './schemas/SchemaDefinition.json' } responses: - '200': { description: ok } + '200': + description: SchemaDefinition created or updated successfully. + '400': + description: Request body is malformed JSON. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '401': + description: Missing or invalid authentication token. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '403': + description: Authenticated subject is not permitted to upsert schemas. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '422': + description: Request body is valid JSON but fails schema validation. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + /v2/agreements: post: operationId: upsertAgreement + summary: Upsert an Agreement + description: Creates or updates a data-sharing agreement between one or more parties. Idempotent on `id`. + tags: [Governance] requestBody: required: true content: application/json: schema: { $ref: './schemas/Agreement.json' } responses: - '200': { description: ok } + '200': + description: Agreement created or updated successfully. + '400': + description: Request body is malformed JSON. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '401': + description: Missing or invalid authentication token. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '403': + description: Authenticated subject is not permitted to upsert agreements. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '422': + description: Request body is valid JSON but fails schema validation. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + /v2/glossary: post: operationId: upsertGlossaryTerm + summary: Upsert a GlossaryTerm + description: Creates or updates a business glossary term with synonyms, tags, and authority links. Idempotent on `id`. + tags: [Metadata] requestBody: required: true content: application/json: schema: { $ref: './schemas/GlossaryTerm.json' } responses: - '200': { description: ok } + '200': + description: GlossaryTerm created or updated successfully. + '400': + description: Request body is malformed JSON. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '401': + description: Missing or invalid authentication token. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '403': + description: Authenticated subject is not permitted to upsert glossary terms. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '422': + description: Request body is valid JSON but fails schema validation. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + /v2/datasets: post: operationId: upsertDataset + summary: Upsert a Dataset + description: Creates or updates a governance-annotated logical view of a PhysicalAsset. Idempotent on `id`. + tags: [Metadata] requestBody: required: true content: application/json: schema: { $ref: './schemas/Dataset.json' } responses: - '200': { description: ok } + '200': + description: Dataset created or updated successfully. + '400': + description: Request body is malformed JSON. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '401': + description: Missing or invalid authentication token. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '403': + description: Authenticated subject is not permitted to upsert datasets. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '422': + description: Request body is valid JSON but fails schema validation. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + /v2/fields: post: operationId: upsertField + summary: Upsert a Field + description: Creates or updates a fully annotated, quality-profiled field bound to a Dataset. Idempotent on `id`. + tags: [Metadata] requestBody: required: true content: application/json: schema: { $ref: './schemas/Field.json' } responses: - '200': { description: ok } + '200': + description: Field created or updated successfully. + '400': + description: Request body is malformed JSON. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '401': + description: Missing or invalid authentication token. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '403': + description: Authenticated subject is not permitted to upsert fields. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '422': + description: Request body is valid JSON but fails schema validation. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + /v2/mappings: post: operationId: upsertMapping + summary: Upsert a MappingSpec + description: Creates or updates a field-to-field semantic mapping with confidence evidence. Idempotent on `id`. + tags: [Metadata] requestBody: required: true content: application/json: schema: { $ref: './schemas/MappingSpec.json' } responses: - '200': { description: ok } + '200': + description: MappingSpec created or updated successfully. + '400': + description: Request body is malformed JSON. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '401': + description: Missing or invalid authentication token. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '403': + description: Authenticated subject is not permitted to upsert mappings. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '422': + description: Request body is valid JSON but fails schema validation. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + /v2/policies: post: operationId: upsertPolicy + summary: Upsert a Policy + description: Creates or updates an access-control policy with subject/object/purpose scope and rules. Idempotent on `id`. + tags: [Governance] requestBody: required: true content: application/json: schema: { $ref: './schemas/Policy.json' } responses: - '200': { description: ok } + '200': + description: Policy created or updated successfully. + '400': + description: Request body is malformed JSON. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '401': + description: Missing or invalid authentication token. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '403': + description: Authenticated subject is not permitted to upsert policies. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '422': + description: Request body is valid JSON but fails schema validation. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + /v2/decisions/evaluate: post: operationId: evaluatePolicy + summary: Evaluate a policy decision + description: | + Evaluates all applicable Policies for the given subject, object, and purpose triple and + returns a signed PolicyDecision (permit, deny, or permitWithObligations). + + The decision is persisted for audit purposes and its URN is returned in the response. + Use the returned `id` to call `POST /v2/tokens/issue` to receive a CapabilityToken. + tags: [Governance] requestBody: required: true + description: The access request context to evaluate. content: application/json: schema: type: object required: [subject, object, purpose] properties: - subject: { $ref: './schemas/SubjectContext.json' } - object: { $ref: './schemas/ObjectContext.json' } - purpose: { type: string } - environment: { type: object } + subject: + $ref: './schemas/SubjectContext.json' + object: + $ref: './schemas/ObjectContext.json' + purpose: + type: string + description: The declared purpose of the access request (e.g. "export", "analytics"). + environment: + type: object + description: Optional ambient environment attributes (device, location, time) for condition evaluation. responses: '200': - description: decision + description: Policy decision evaluated and persisted. content: application/json: schema: { $ref: './schemas/PolicyDecision.json' } + '400': + description: Request body is malformed JSON. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '401': + description: Missing or invalid authentication token. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '403': + description: Authenticated subject is not permitted to call the policy evaluation endpoint. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '422': + description: Request body is valid JSON but fails schema validation. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + /v2/tokens/issue: post: operationId: issueToken + summary: Issue a CapabilityToken + description: | + Issues a short-lived, signed CapabilityToken derived from a PolicyDecision with outcome + `permit` or `permitWithObligations`. The token scopes the holder to the datasets, fields, + assets, and operations approved by the decision. + tags: [Governance] requestBody: required: true + description: The PolicyDecision from which to derive the token. content: application/json: schema: { $ref: './schemas/PolicyDecision.json' } responses: '200': - description: token + description: CapabilityToken issued successfully. content: application/json: schema: { $ref: './schemas/CapabilityToken.json' } + '400': + description: Request body is malformed JSON. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '401': + description: Missing or invalid authentication token. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '403': + description: The PolicyDecision does not permit token issuance (outcome is deny). + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '422': + description: Request body is valid JSON but fails schema validation. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + /v2/workflows: post: operationId: upsertWorkflow + summary: Upsert a WorkflowSpec + description: Creates or updates a directed acyclic graph of WorkflowNodes with triggers and policy bindings. Idempotent on `id`. + tags: [Execution] requestBody: required: true content: application/json: schema: { $ref: './schemas/WorkflowSpec.json' } responses: - '200': { description: ok } + '200': + description: WorkflowSpec created or updated successfully. + '400': + description: Request body is malformed JSON. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '401': + description: Missing or invalid authentication token. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '403': + description: Authenticated subject is not permitted to upsert workflows. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '422': + description: Request body is valid JSON but fails schema validation. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + /v2/runs: post: operationId: recordRun + summary: Record a RunRecord + description: Persists the audit record of a completed workload execution, referencing the CapabilityToken and DataSphere used. Idempotent on `id`. + tags: [Execution] requestBody: required: true content: application/json: schema: { $ref: './schemas/RunRecord.json' } responses: - '200': { description: ok } + '200': + description: RunRecord persisted successfully. + '400': + description: Request body is malformed JSON. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '401': + description: Missing or invalid authentication token. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '403': + description: Authenticated subject is not permitted to record runs. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '422': + description: Request body is valid JSON but fails schema validation. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + /v2/provenance: post: operationId: recordProvenance + summary: Record a ProvenanceRecord + description: Persists a W3C PROV-compatible lineage record linking a RunRecord to its input and output entities. Idempotent on `id`. + tags: [Execution] requestBody: required: true content: application/json: schema: { $ref: './schemas/ProvenanceRecord.json' } responses: - '200': { description: ok } + '200': + description: ProvenanceRecord persisted successfully. + '400': + description: Request body is malformed JSON. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '401': + description: Missing or invalid authentication token. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '403': + description: Authenticated subject is not permitted to record provenance. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '422': + description: Request body is valid JSON but fails schema validation. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + /v2/comments: post: operationId: createComment + summary: Create a Comment + description: Creates a free-text annotation attached to any addressable object identified by a URN. Idempotent on `id`. + tags: [Collaboration] requestBody: required: true content: application/json: schema: { $ref: './schemas/Comment.json' } responses: - '200': { description: ok } + '200': + description: Comment created successfully. + '400': + description: Request body is malformed JSON. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '401': + description: Missing or invalid authentication token. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '403': + description: Authenticated subject is not permitted to create comments. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '422': + description: Request body is valid JSON but fails schema validation. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + /v2/ratings: post: operationId: createRating + summary: Create a Rating + description: Creates a 1–5 star rating attached to any addressable object. Idempotent on `id`. + tags: [Collaboration] requestBody: required: true content: application/json: schema: { $ref: './schemas/Rating.json' } responses: - '200': { description: ok } + '200': + description: Rating created successfully. + '400': + description: Request body is malformed JSON. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '401': + description: Missing or invalid authentication token. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '403': + description: Authenticated subject is not permitted to create ratings. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + '422': + description: Request body is valid JSON but fails schema validation. + content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } + diff --git a/schemas/AgentSession.json b/schemas/AgentSession.json index d9ddf72..66a938d 100644 --- a/schemas/AgentSession.json +++ b/schemas/AgentSession.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/AgentSession.json", "title": "AgentSession", + "description": "A single autonomous agent session. Tracks the role, mode, execution substrate, bound skills and memories, and all execution decisions made during the session.", "type": "object", "additionalProperties": false, "required": [ @@ -22,20 +23,24 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:session:" + "pattern": "^urn:srcos:session:", + "description": "Stable URN identifier. Pattern: urn:srcos:session:" }, "type": { - "const": "AgentSession" + "const": "AgentSession", + "description": "Discriminator constant \u2014 always \"AgentSession\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "parentSessionRef": { "type": [ "string", "null" ], - "pattern": "^urn:srcos:session:" + "pattern": "^urn:srcos:session:", + "description": "URN of the parent session if this is a sub-session (e.g. an explorer launched by a main session). Null for root sessions." }, "role": { "enum": [ @@ -47,7 +52,8 @@ "auditor", "reverser", "custom" - ] + ], + "description": "The functional role this session plays: main (top-level coordinator), explorer (research), planner, executor, reviewer, auditor, reverser (undo), or custom." }, "status": { "enum": [ @@ -60,7 +66,8 @@ "canceled", "merged", "reversed" - ] + ], + "description": "Lifecycle state of the session: created \u2192 waiting \u2192 running \u2192 paused \u2192 completed/failed/canceled/merged/reversed." }, "mode": { "enum": [ @@ -68,16 +75,19 @@ "ask", "execute", "review" - ] + ], + "description": "The current operating mode: plan (design only), ask (gather information), execute (make changes), or review (assess results)." }, "workspaceRef": { - "type": "string" + "type": "string", + "description": "Identifier of the workspace (repository, project, or environment) this session operates in." }, "worktreeRef": { "type": [ "string", "null" - ] + ], + "description": "Optional reference to a git worktree if the session works in an isolated branch checkout." }, "substrate": { "enum": [ @@ -87,51 +97,59 @@ "background", "event-pushed", "ci" - ] + ], + "description": "Where the agent runtime is hosted: local (developer machine), remote-local (remote dev), cloud, background (async), event-pushed, or ci (CI pipeline)." }, "surface": { - "$ref": "ExecutionSurface.json" + "$ref": "ExecutionSurface.json", + "description": "The execution surface constraints (sandbox mode, network policy, protected paths) applied to this session." }, "provider": { "type": [ "string", "null" - ] + ], + "description": "Optional name of the AI model provider or runtime host." }, "skillRefs": { "type": "array", "items": { "type": "string", "pattern": "^urn:srcos:skill:" - } + }, + "description": "URNs of the SkillManifests available to this session." }, "memoryRefs": { "type": "array", "items": { "type": "string", "pattern": "^urn:srcos:memory:" - } + }, + "description": "URNs of the MemoryEntries loaded into this session." }, "transcriptRef": { "type": [ "string", "null" ], - "pattern": "^urn:srcos:transcript:" + "pattern": "^urn:srcos:transcript:", + "description": "Optional URN of the conversation transcript artifact." }, "decisionRefs": { "type": "array", "items": { "type": "string", "pattern": "^urn:srcos:exec-decision:" - } + }, + "description": "URNs of all ExecutionDecisions recorded during this session." }, "telemetryRefs": { "type": "array", "items": { "type": "string", "pattern": "^urn:srcos:telemetry:" - } + }, + "description": "URNs of TelemetryEvents emitted during this session." }, "time": { "type": "object", @@ -151,7 +169,8 @@ ], "format": "date-time" } - } + }, + "description": "Session timing: startedAt (required) and optional endedAt." } } } diff --git a/schemas/Agreement.json b/schemas/Agreement.json index cbace80..d187284 100644 --- a/schemas/Agreement.json +++ b/schemas/Agreement.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/Agreement.json", "title": "Agreement", + "description": "A data-sharing agreement between one or more parties. Captures the license, restrictions, retention period, jurisdiction, and effective date range.", "type": "object", "additionalProperties": false, "required": [ @@ -16,29 +17,35 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:agreement:" + "pattern": "^urn:srcos:agreement:", + "description": "Stable URN identifier. Pattern: urn:srcos:agreement:" }, "type": { - "const": "Agreement" + "const": "Agreement", + "description": "Discriminator constant \u2014 always \"Agreement\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "title": { - "type": "string" + "type": "string", + "description": "Human-readable name of the agreement." }, "description": { "type": [ "string", "null" - ] + ], + "description": "Optional longer description of the agreement's purpose or context." }, "parties": { "type": "array", "items": { "$ref": "Party.json" }, - "minItems": 1 + "minItems": 1, + "description": "The signatories to this agreement. At least one party is required." }, "terms": { "type": "object", @@ -74,7 +81,8 @@ "null" ] } - } + }, + "description": "The legal and operational terms: license identifier, restrictions list, attribution requirement, retention period, and jurisdiction." }, "effective": { "type": "object", @@ -94,13 +102,15 @@ ], "format": "date-time" } - } + }, + "description": "The date range for which this agreement is in force. `end` is null for open-ended agreements." }, "links": { "type": "array", "items": { "$ref": "Link.json" - } + }, + "description": "Supplementary hyperlinks (e.g. to the full legal text)." } } -} \ No newline at end of file +} diff --git a/schemas/AuthorityLink.json b/schemas/AuthorityLink.json index bd9eadf..9dd09ba 100644 --- a/schemas/AuthorityLink.json +++ b/schemas/AuthorityLink.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/AuthorityLink.json", "title": "AuthorityLink", + "description": "A pointer to a specific entry in an external controlled vocabulary or authority system (e.g. SNOMED, ISO 27001, an internal wiki).", "type": "object", "additionalProperties": false, "required": [ @@ -10,17 +11,20 @@ ], "properties": { "system": { - "type": "string" + "type": "string", + "description": "Identifier of the authority system or controlled vocabulary (e.g. \"SNOMED\", \"ISO-27001\", \"internal-wiki\")." }, "value": { - "type": "string" + "type": "string", + "description": "The identifier or code within the authority system." }, "url": { "type": [ "string", "null" ], - "format": "uri" + "format": "uri", + "description": "Optional resolvable URL to the specific entry in the authority system." } } -} \ No newline at end of file +} diff --git a/schemas/CapabilityToken.json b/schemas/CapabilityToken.json index 2b6f370..65f3162 100644 --- a/schemas/CapabilityToken.json +++ b/schemas/CapabilityToken.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/CapabilityToken.json", "title": "CapabilityToken", + "description": "A short-lived, cryptographically signed access grant derived from a PolicyDecision. Scopes the holder to specific datasets, fields, assets, and operations.", "type": "object", "additionalProperties": false, "required": [ @@ -15,10 +16,12 @@ ], "properties": { "tokenId": { - "type": "string" + "type": "string", + "description": "Unique identifier for this token (plain string, not a URN)." }, "subject": { - "$ref": "SubjectContext.json" + "$ref": "SubjectContext.json", + "description": "The subject context describing the token holder." }, "scope": { "type": "object", @@ -59,29 +62,36 @@ ] } } - } + }, + "description": "The resources and operations this token grants access to." }, "purpose": { - "type": "string" + "type": "string", + "description": "The declared purpose for which this token may be used (e.g. \"export\", \"analytics\")." }, "decisionRef": { "type": "string", - "pattern": "^urn:srcos:decision:" + "pattern": "^urn:srcos:decision:", + "description": "URN of the PolicyDecision that authorised this token. Pattern: urn:srcos:decision:" }, "obligations": { "type": "array", "items": { "$ref": "Obligation.json" - } + }, + "description": "Obligations the token holder must fulfil when exercising this token." }, "iat": { - "type": "integer" + "type": "integer", + "description": "Issued-at timestamp as a Unix epoch integer (seconds since 1970-01-01T00:00:00Z)." }, "exp": { - "type": "integer" + "type": "integer", + "description": "Expiry timestamp as a Unix epoch integer (seconds since 1970-01-01T00:00:00Z)." }, "signature": { - "type": "string" + "type": "string", + "description": "Cryptographic signature over the token contents (format defined by the issuing service)." } } -} \ No newline at end of file +} diff --git a/schemas/Comment.json b/schemas/Comment.json index fc9bbbb..04176fe 100644 --- a/schemas/Comment.json +++ b/schemas/Comment.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/Comment.json", "title": "Comment", + "description": "A free-text annotation attached to any addressable object identified by a URN.", "type": "object", "additionalProperties": false, "required": [ @@ -16,26 +17,33 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:comment:" + "pattern": "^urn:srcos:comment:", + "description": "Stable URN identifier. Pattern: urn:srcos:comment:" }, "type": { - "const": "Comment" + "const": "Comment", + "description": "Discriminator constant \u2014 always \"Comment\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "targetId": { - "type": "string" + "type": "string", + "description": "URN of the object this comment is attached to." }, "author": { - "type": "string" + "type": "string", + "description": "URN of the subject who wrote the comment." }, "createdAt": { "type": "string", - "format": "date-time" + "format": "date-time", + "description": "ISO 8601 date-time when the comment was created." }, "body": { - "type": "string" + "type": "string", + "description": "The comment text (plain text or Markdown)." } } -} \ No newline at end of file +} diff --git a/schemas/Community.json b/schemas/Community.json index df81cba..237b0d9 100644 --- a/schemas/Community.json +++ b/schemas/Community.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/Community.json", "title": "Community", + "description": "A named group of subject URNs, used to manage team-level access and notification subscriptions.", "type": "object", "additionalProperties": false, "required": [ @@ -13,34 +14,41 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:community:" + "pattern": "^urn:srcos:community:", + "description": "Stable URN identifier. Pattern: urn:srcos:community:" }, "type": { - "const": "Community" + "const": "Community", + "description": "Discriminator constant \u2014 always \"Community\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "name": { - "type": "string" + "type": "string", + "description": "Human-readable name of the community." }, "description": { "type": [ "string", "null" - ] + ], + "description": "Optional description of the community's purpose." }, "members": { "type": "array", "items": { "type": "string" - } + }, + "description": "List of subject URNs that are members of this community." }, "links": { "type": "array", "items": { "$ref": "Link.json" - } + }, + "description": "Supplementary hyperlinks (e.g. team chat, wiki page)." } } -} \ No newline at end of file +} diff --git a/schemas/Connector.json b/schemas/Connector.json index 90dcea3..7f50152 100644 --- a/schemas/Connector.json +++ b/schemas/Connector.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/Connector.json", "title": "Connector", + "description": "A named, typed connection configuration for a physical data store (S3, GCS, Azure Blob, RDBMS, Kafka, filesystem, HTTP API, or lakehouse).", "type": "object", "additionalProperties": false, "required": [ @@ -15,16 +16,20 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:connector:" + "pattern": "^urn:srcos:connector:", + "description": "Stable URN identifier. Pattern: urn:srcos:connector:" }, "type": { - "const": "Connector" + "const": "Connector", + "description": "Discriminator constant \u2014 always \"Connector\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "name": { - "type": "string" + "type": "string", + "description": "Human-readable name for this connector." }, "kind": { "enum": [ @@ -36,11 +41,13 @@ "filesystem", "httpApi", "lakehouse" - ] + ], + "description": "The storage technology type: s3, gcs, azureBlob, rdbms, kafka, filesystem, httpApi, or lakehouse." }, "config": { "type": "object", - "additionalProperties": true + "additionalProperties": true, + "description": "Connector-specific configuration object. Structure is defined by the `kind` value." }, "status": { "enum": [ @@ -48,7 +55,8 @@ "disabled", "deprecated" ], - "default": "active" + "default": "active", + "description": "Operational status: active (default), disabled, or deprecated." } } -} \ No newline at end of file +} diff --git a/schemas/DataRef.json b/schemas/DataRef.json index 68b873f..1bd8838 100644 --- a/schemas/DataRef.json +++ b/schemas/DataRef.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/DataRef.json", "title": "DataRef", + "description": "A typed pointer to a data entity (dataset, asset, stream topic, or file) with optional field-path restrictions.", "type": "object", "additionalProperties": false, "required": [ @@ -15,16 +16,19 @@ "asset", "streamTopic", "file" - ] + ], + "description": "The type of data entity referenced: dataset, asset, streamTopic, or file." }, "id": { - "type": "string" + "type": "string", + "description": "URN or identifier of the referenced entity." }, "fieldPaths": { "type": "array", "items": { "type": "string" - } + }, + "description": "Optional JSONPath expressions restricting which fields of the entity are in scope (e.g. \"$.patient.dateOfBirth\")." } } -} \ No newline at end of file +} diff --git a/schemas/DataSphere.json b/schemas/DataSphere.json index 5c0dd2c..e6252bd 100644 --- a/schemas/DataSphere.json +++ b/schemas/DataSphere.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/DataSphere.json", "title": "DataSphere", + "description": "A bounded, policy-controlled execution environment. Defines the zone, network policy, and integrity controls under which a workload runs.", "type": "object", "additionalProperties": false, "required": [ @@ -13,10 +14,12 @@ "properties": { "sphereId": { "type": "string", - "pattern": "^urn:srcos:sphere:" + "pattern": "^urn:srcos:sphere:", + "description": "Stable URN identifier. Pattern: urn:srcos:sphere:" }, "name": { - "type": "string" + "type": "string", + "description": "Human-readable name for this data sphere." }, "boundary": { "type": "object", @@ -37,7 +40,8 @@ "null" ] } - } + }, + "description": "Zone and policy boundaries: the logical zone name, an optional network policy reference, and an optional storage policy reference." }, "controls": { "type": "object", @@ -60,7 +64,8 @@ "strict" ] } - } + }, + "description": "Enforcement controls: the access enforcer identifier, provenance recording level, and container attestation level." } } -} \ No newline at end of file +} diff --git a/schemas/Dataset.json b/schemas/Dataset.json index 9b7a198..558ff3b 100644 --- a/schemas/Dataset.json +++ b/schemas/Dataset.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/Dataset.json", "title": "Dataset", + "description": "A logical, governance-annotated view of a PhysicalAsset. References the physical asset, schema, and all applicable agreements and classification tags.", "type": "object", "additionalProperties": false, "required": [ @@ -17,30 +18,37 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:dataset:" + "pattern": "^urn:srcos:dataset:", + "description": "Stable URN identifier. Pattern: urn:srcos:dataset:" }, "type": { - "const": "Dataset" + "const": "Dataset", + "description": "Discriminator constant \u2014 always \"Dataset\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "name": { - "type": "string" + "type": "string", + "description": "Human-readable fully-qualified name (e.g. \"Domain.Subdomain.EntityName\")." }, "description": { "type": [ "string", "null" - ] + ], + "description": "Optional description of the dataset's content and purpose." }, "assetRef": { "type": "string", - "pattern": "^urn:srcos:asset:" + "pattern": "^urn:srcos:asset:", + "description": "URN of the PhysicalAsset that backs this dataset. Pattern: urn:srcos:asset:" }, "schemaRef": { "type": "string", - "pattern": "^urn:srcos:schema:" + "pattern": "^urn:srcos:schema:", + "description": "URN of the SchemaDefinition that describes this dataset's structure. Pattern: urn:srcos:schema:" }, "governance": { "type": "object", @@ -80,7 +88,8 @@ ] } } - } + }, + "description": "Governance metadata: classification tags, applicable agreements, usage definitions, and zone membership." }, "lifecycle": { "type": "object", @@ -104,13 +113,15 @@ "type": "string", "format": "date-time" } - } + }, + "description": "Lifecycle state and the timestamp when the dataset entered that state." }, "links": { "type": "array", "items": { "$ref": "Link.json" - } + }, + "description": "Supplementary hyperlinks." } } -} \ No newline at end of file +} diff --git a/schemas/EntityField.json b/schemas/EntityField.json index ce4c0a2..5c4f14e 100644 --- a/schemas/EntityField.json +++ b/schemas/EntityField.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/EntityField.json", "title": "EntityField", + "description": "A field descriptor inside a SchemaDefinition. Carries the data type, nullability, valid-value constraints, classification tags, and glossary term links.", "type": "object", "additionalProperties": false, "required": [ @@ -10,30 +11,36 @@ ], "properties": { "name": { - "type": "string" + "type": "string", + "description": "Field name or JSONPath within the schema (e.g. \"patient.dateOfBirth\")." }, "dataType": { - "type": "string" + "type": "string", + "description": "The logical data type (e.g. \"string\", \"integer\", \"date\", \"boolean\")." }, "nullable": { "type": "boolean", - "default": true + "default": true, + "description": "Whether this field may contain null values. Defaults to true." }, "validValues": { - "$ref": "ValidValues.json" + "$ref": "ValidValues.json", + "description": "Optional valid-value constraint: enumeration, range, or regex." }, "tags": { "type": "array", "items": { "$ref": "TagAssignment.json" - } + }, + "description": "Classification tags applied to this field (e.g. PII tags)." }, "glossaryTerms": { "type": "array", "items": { "type": "string", "pattern": "^urn:srcos:glossary:" - } + }, + "description": "URNs of GlossaryTerms that this field represents. Pattern: urn:srcos:glossary:" } } -} \ No newline at end of file +} diff --git a/schemas/EventEnvelope.json b/schemas/EventEnvelope.json index 73d8bb7..83f73b4 100644 --- a/schemas/EventEnvelope.json +++ b/schemas/EventEnvelope.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/EventEnvelope.json", "title": "EventEnvelope", + "description": "The universal wrapper for all AsyncAPI channel messages. Carries event identity, type, actor, target object, typed payload, and optional integrity hashes.", "type": "object", "additionalProperties": false, "required": [ @@ -16,17 +17,21 @@ "properties": { "eventId": { "type": "string", - "pattern": "^urn:srcos:event:" + "pattern": "^urn:srcos:event:", + "description": "Stable URN identifier for this event. Pattern: urn:srcos:event:" }, "eventType": { - "type": "string" + "type": "string", + "description": "Identifies the domain event (e.g. \"DatasetUpserted\", \"RunRecorded\", \"PolicyEvaluated\")." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "occurredAt": { "type": "string", - "format": "date-time" + "format": "date-time", + "description": "ISO 8601 date-time when the domain event occurred." }, "actor": { "type": "object", @@ -44,14 +49,17 @@ "null" ] } - } + }, + "description": "The subject that triggered this event (subjectId URN and optional IP address)." }, "objectId": { - "type": "string" + "type": "string", + "description": "URN of the primary object affected by this event." }, "payload": { "type": "object", - "additionalProperties": true + "additionalProperties": true, + "description": "The full domain object payload (typed by `eventType`)." }, "integrity": { "type": "object", @@ -69,7 +77,8 @@ "null" ] } - } + }, + "description": "Optional integrity envelope: hash of the event payload and/or a cryptographic signature." } } -} \ No newline at end of file +} diff --git a/schemas/Exception.json b/schemas/Exception.json index a4ddf23..8bfe518 100644 --- a/schemas/Exception.json +++ b/schemas/Exception.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/Exception.json", "title": "Exception", + "description": "A time-limited exemption from a Policy rule. Attached to a Policy to allow specific cases that would otherwise be denied.", "type": "object", "additionalProperties": false, "required": [ @@ -10,17 +11,20 @@ ], "properties": { "name": { - "type": "string" + "type": "string", + "description": "Machine-readable identifier for this exception (e.g. \"approved-research-exemption\")." }, "reason": { - "type": "string" + "type": "string", + "description": "Human-readable explanation of why this exception is permitted." }, "expiresAt": { "type": [ "string", "null" ], - "format": "date-time" + "format": "date-time", + "description": "Optional ISO 8601 date-time after which this exception is no longer valid." } } -} \ No newline at end of file +} diff --git a/schemas/ExecutionDecision.json b/schemas/ExecutionDecision.json index 9df827f..6cb0c4d 100644 --- a/schemas/ExecutionDecision.json +++ b/schemas/ExecutionDecision.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/ExecutionDecision.json", "title": "ExecutionDecision", + "description": "An immutable audit record of a single agent execution decision (allow, deny, ask, defer, or rewrite) made during an AgentSession.", "type": "object", "additionalProperties": false, "required": [ @@ -17,24 +18,29 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:exec-decision:" + "pattern": "^urn:srcos:exec-decision:", + "description": "Stable URN identifier. Pattern: urn:srcos:exec-decision:" }, "type": { - "const": "ExecutionDecision" + "const": "ExecutionDecision", + "description": "Discriminator constant \u2014 always \"ExecutionDecision\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "sessionRef": { "type": "string", - "pattern": "^urn:srcos:session:" + "pattern": "^urn:srcos:session:", + "description": "URN of the AgentSession in which this decision was made. Pattern: urn:srcos:session:" }, "toolRequestRef": { "type": [ "string", "null" ], - "pattern": "^urn:srcos:tool:" + "pattern": "^urn:srcos:tool:", + "description": "Optional URN of the tool call or action request this decision responds to. Pattern: urn:srcos:tool:" }, "decision": { "enum": [ @@ -43,45 +49,53 @@ "ask", "defer", "rewrite" - ] + ], + "description": "The outcome: allow (proceed as requested), deny (block), ask (prompt user), defer (pause for later), or rewrite (modify input before proceeding)." }, "reason": { - "type": "string" + "type": "string", + "description": "Human-readable explanation of why this decision was reached." }, "updatedInput": { "type": [ "object", "null" ], - "additionalProperties": true + "additionalProperties": true, + "description": "When `decision` is \"rewrite\", the modified input object to use instead of the original." }, "policyRef": { "type": [ "string", "null" ], - "pattern": "^urn:srcos:policy:" + "pattern": "^urn:srcos:policy:", + "description": "Optional URN of the Policy that drove this decision. Pattern: urn:srcos:policy:" }, "obligations": { "type": "array", "items": { "type": "string" - } + }, + "description": "Obligation identifiers the session must fulfil as a result of this decision." }, "issuedAt": { "type": "string", - "format": "date-time" + "format": "date-time", + "description": "ISO 8601 date-time when this decision was recorded." }, "expiresAt": { "type": [ "string", "null" ], - "format": "date-time" + "format": "date-time", + "description": "Optional ISO 8601 date-time after which this decision is no longer valid." }, "decisionHash": { "type": "string", - "pattern": "^sha256:" + "pattern": "^sha256:", + "description": "sha256: prefixed hash of the canonical decision payload for tamper-evidence." } } } diff --git a/schemas/ExecutionSurface.json b/schemas/ExecutionSurface.json index cfe2242..c1276b1 100644 --- a/schemas/ExecutionSurface.json +++ b/schemas/ExecutionSurface.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/ExecutionSurface.json", "title": "ExecutionSurface", + "description": "The sandboxing and runtime constraints of an agent's execution environment: PTY, working directory, sandbox mode, network mode, and protected path list.", "type": "object", "additionalProperties": false, "required": [ @@ -17,16 +18,20 @@ ], "properties": { "pty": { - "type": "boolean" + "type": "boolean", + "description": "Whether a pseudo-terminal (PTY) should be allocated for the agent process." }, "workdir": { - "type": "string" + "type": "string", + "description": "Absolute path to the working directory for the agent session." }, "background": { - "type": "boolean" + "type": "boolean", + "description": "Whether the agent runs as a background (non-interactive) process." }, "reviewOnly": { - "type": "boolean" + "type": "boolean", + "description": "When true, the agent may read and analyse but must not modify anything." }, "worktreeStrategy": { "enum": [ @@ -34,7 +39,8 @@ "existing", "create-temp", "named" - ] + ], + "description": "How git worktrees are managed: none (no worktree), existing (use current), create-temp (ephemeral), or named (persistent named worktree)." }, "sandboxMode": { "enum": [ @@ -43,35 +49,41 @@ "container", "vm", "browser-sandbox" - ] + ], + "description": "Isolation level: none, user-level sandbox, container, VM, or browser sandbox." }, "networkMode": { "enum": [ "none", "allowlist", "full" - ] + ], + "description": "Network access: none (air-gapped), allowlist (egress restricted to egressAllowlist), or full (unrestricted)." }, "egressAllowlist": { "type": "array", "items": { "type": "string" - } + }, + "description": "Hostnames or CIDR ranges permitted for outbound network access when networkMode is \"allowlist\"." }, "elevated": { - "type": "boolean" + "type": "boolean", + "description": "Whether the agent runs with elevated (e.g. root or administrator) privileges." }, "protectedPaths": { "type": "array", "items": { "type": "string" - } + }, + "description": "File system paths the agent must not read from or write to." }, "approvalProfile": { "type": [ "string", "null" - ] + ], + "description": "Optional identifier of a human-approval profile that governs when the agent must pause and wait for explicit sign-off." } } } diff --git a/schemas/ExperimentFlag.json b/schemas/ExperimentFlag.json index b20b8c2..fdfd00a 100644 --- a/schemas/ExperimentFlag.json +++ b/schemas/ExperimentFlag.json @@ -2,17 +2,62 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/ExperimentFlag.json", "title": "ExperimentFlag", + "description": "A feature flag with a governed lifecycle: off \u2192 shadow \u2192 internal \u2192 beta \u2192 on \u2192 retired. Carries a kill-switch for emergency disablement.", "type": "object", "additionalProperties": false, - "required": ["id","type","specVersion","name","state"], + "required": [ + "id", + "type", + "specVersion", + "name", + "state" + ], "properties": { - "id": {"type": "string", "pattern": "^urn:srcos:flag:"}, - "type": {"const": "ExperimentFlag"}, - "specVersion": {"type": "string"}, - "name": {"type": "string"}, - "state": {"enum": ["off","shadow","internal","beta","on","retired"]}, - "owner": {"type": ["string","null"]}, - "description": {"type": ["string","null"]}, - "killSwitch": {"type": "boolean"} + "id": { + "type": "string", + "pattern": "^urn:srcos:flag:", + "description": "Stable URN identifier. Pattern: urn:srcos:flag:" + }, + "type": { + "const": "ExperimentFlag", + "description": "Discriminator constant \u2014 always \"ExperimentFlag\"." + }, + "specVersion": { + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." + }, + "name": { + "type": "string", + "description": "Human-readable name of the feature flag (e.g. \"new-obfuscation-algorithm\")." + }, + "state": { + "enum": [ + "off", + "shadow", + "internal", + "beta", + "on", + "retired" + ], + "description": "Current lifecycle state: off, shadow (dark launch), internal (staff only), beta, on (general availability), or retired." + }, + "owner": { + "type": [ + "string", + "null" + ], + "description": "Optional URN or username of the team or person responsible for this flag." + }, + "description": { + "type": [ + "string", + "null" + ], + "description": "Optional description of what feature this flag controls." + }, + "killSwitch": { + "type": "boolean", + "description": "When true, activating this flag will immediately disable the feature regardless of rollout rules." + } } } diff --git a/schemas/Field.json b/schemas/Field.json index 30b8792..16dce18 100644 --- a/schemas/Field.json +++ b/schemas/Field.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/Field.json", "title": "Field", + "description": "A fully annotated, quality-profiled field bound to a specific Dataset. Extends EntityField with a live quality profile, statistics, and external links.", "type": "object", "additionalProperties": false, "required": [ @@ -17,23 +18,29 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:field:" + "pattern": "^urn:srcos:field:", + "description": "Stable URN identifier. Pattern: urn:srcos:field:" }, "type": { - "const": "Field" + "const": "Field", + "description": "Discriminator constant \u2014 always \"Field\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "datasetId": { "type": "string", - "pattern": "^urn:srcos:dataset:" + "pattern": "^urn:srcos:dataset:", + "description": "URN of the Dataset this field belongs to. Pattern: urn:srcos:dataset:" }, "path": { - "type": "string" + "type": "string", + "description": "JSONPath expression locating this field within the dataset (e.g. \"$.patient.dateOfBirth\")." }, "dataType": { - "type": "string" + "type": "string", + "description": "The logical data type of this field (e.g. \"string\", \"integer\", \"date\")." }, "semantics": { "type": "object", @@ -61,7 +68,8 @@ "$ref": "AuthorityLink.json" } } - } + }, + "description": "Semantic annotations: classification tags, linked glossary terms, and authority links." }, "quality": { "type": "object", @@ -76,13 +84,15 @@ "$ref": "QualityMetric.json" } } - } + }, + "description": "Quality metadata: column statistics profile and named quality dimension scores." }, "links": { "type": "array", "items": { "$ref": "Link.json" - } + }, + "description": "Supplementary hyperlinks." } } -} \ No newline at end of file +} diff --git a/schemas/FrustrationSignal.json b/schemas/FrustrationSignal.json index 9e92b23..b3feca5 100644 --- a/schemas/FrustrationSignal.json +++ b/schemas/FrustrationSignal.json @@ -2,16 +2,58 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/FrustrationSignal.json", "title": "FrustrationSignal", + "description": "A behavioural telemetry signal indicating that an agent or user is experiencing difficulty (e.g. repeated failure, tool loop, user interrupt).", "type": "object", "additionalProperties": false, - "required": ["id","type","specVersion","sessionRef","signal","capturedAt"], + "required": [ + "id", + "type", + "specVersion", + "sessionRef", + "signal", + "capturedAt" + ], "properties": { - "id": {"type": "string", "pattern": "^urn:srcos:frustration:"}, - "type": {"const": "FrustrationSignal"}, - "specVersion": {"type": "string"}, - "sessionRef": {"type": "string", "pattern": "^urn:srcos:session:"}, - "signal": {"enum": ["strong-negative-language","cancel","repeated-failure","tool-loop","user-interrupt"]}, - "count": {"type": ["integer","null"], "minimum": 0}, - "capturedAt": {"type": "string", "format": "date-time"} + "id": { + "type": "string", + "pattern": "^urn:srcos:frustration:", + "description": "Stable URN identifier. Pattern: urn:srcos:frustration:" + }, + "type": { + "const": "FrustrationSignal", + "description": "Discriminator constant \u2014 always \"FrustrationSignal\"." + }, + "specVersion": { + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." + }, + "sessionRef": { + "type": "string", + "pattern": "^urn:srcos:session:", + "description": "URN of the AgentSession in which this signal was observed. Pattern: urn:srcos:session:" + }, + "signal": { + "enum": [ + "strong-negative-language", + "cancel", + "repeated-failure", + "tool-loop", + "user-interrupt" + ], + "description": "The observed signal type: strong-negative-language, cancel, repeated-failure, tool-loop, or user-interrupt." + }, + "count": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "Number of times this signal was observed in the session (null if not counted)." + }, + "capturedAt": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 date-time when this signal was first captured." + } } } diff --git a/schemas/GlossaryTerm.json b/schemas/GlossaryTerm.json index b731cc7..4773a9d 100644 --- a/schemas/GlossaryTerm.json +++ b/schemas/GlossaryTerm.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/GlossaryTerm.json", "title": "GlossaryTerm", + "description": "A defined business term with synonyms, classification tags, authority links to external vocabularies, and links to related terms.", "type": "object", "additionalProperties": false, "required": [ @@ -14,50 +15,60 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:glossary:" + "pattern": "^urn:srcos:glossary:", + "description": "Stable URN identifier. Pattern: urn:srcos:glossary:" }, "type": { - "const": "GlossaryTerm" + "const": "GlossaryTerm", + "description": "Discriminator constant \u2014 always \"GlossaryTerm\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "name": { - "type": "string" + "type": "string", + "description": "The canonical name of the term (e.g. \"Date of Birth\")." }, "definition": { - "type": "string" + "type": "string", + "description": "The authoritative definition of the term." }, "synonyms": { "type": "array", "items": { "type": "string" - } + }, + "description": "Alternative names or abbreviations for this term (e.g. [\"DOB\", \"birth date\"])." }, "tags": { "type": "array", "items": { "$ref": "TagAssignment.json" - } + }, + "description": "Classification tags (e.g. PII category tags) applied to this term." }, "authorityLinks": { "type": "array", "items": { "$ref": "AuthorityLink.json" - } + }, + "description": "Links to definitions of this term in external authority systems." }, "relatedTerms": { "type": "array", "items": { "type": "string", "pattern": "^urn:srcos:glossary:" - } + }, + "description": "URNs of related GlossaryTerms. Pattern: urn:srcos:glossary:" }, "links": { "type": "array", "items": { "$ref": "Link.json" - } + }, + "description": "Supplementary hyperlinks." } } -} \ No newline at end of file +} diff --git a/schemas/Link.json b/schemas/Link.json index 65cc718..5cae44c 100644 --- a/schemas/Link.json +++ b/schemas/Link.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/Link.json", "title": "Link", + "description": "A typed hyperlink in the HAL/JSON+HAL style, carrying a relation type (`rel`) and an absolute URI (`href`).", "type": "object", "additionalProperties": false, "required": [ @@ -10,16 +11,19 @@ ], "properties": { "rel": { - "type": "string" + "type": "string", + "description": "The link relation type (e.g. \"self\", \"documentation\", \"related\"). Should be an IANA-registered relation or a custom URI." }, "href": { - "type": "string" + "type": "string", + "description": "The absolute URI of the linked resource." }, "type": { "type": [ "string", "null" - ] + ], + "description": "Optional MIME type of the linked resource (e.g. \"application/json\")." } } -} \ No newline at end of file +} diff --git a/schemas/MappingEvidence.json b/schemas/MappingEvidence.json index c4213dc..62ad1c3 100644 --- a/schemas/MappingEvidence.json +++ b/schemas/MappingEvidence.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/MappingEvidence.json", "title": "MappingEvidence", + "description": "A single piece of evidence supporting a MappingSpec, produced by one specific matching method (label similarity, value overlap, ontology anchor, etc.).", "type": "object", "additionalProperties": false, "required": [ @@ -18,24 +19,28 @@ "kvOverlap", "ontologyAnchor", "blocking" - ] + ], + "description": "The matching method: labelExact, labelStringSim (string similarity), valueCosine, valueContainment, kvOverlap, ontologyAnchor, or blocking." }, "score": { "type": "number", "minimum": 0, - "maximum": 1 + "maximum": 1, + "description": "Confidence score for this evidence item, in the range [0, 1]." }, "notes": { "type": [ "string", "null" - ] + ], + "description": "Optional human-readable notes about this evidence." }, "artifacts": { "type": "array", "items": { "type": "string" - } + }, + "description": "Identifiers of the artifacts (profiles, labels, ontologies) used to produce this evidence." } } -} \ No newline at end of file +} diff --git a/schemas/MappingSpec.json b/schemas/MappingSpec.json index 55b1195..6adcf67 100644 --- a/schemas/MappingSpec.json +++ b/schemas/MappingSpec.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/MappingSpec.json", "title": "MappingSpec", + "description": "A field-to-field semantic mapping between two datasets, with an aggregated confidence score and a multi-method evidence trail.", "type": "object", "additionalProperties": false, "required": [ @@ -17,13 +18,16 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:mapping:" + "pattern": "^urn:srcos:mapping:", + "description": "Stable URN identifier. Pattern: urn:srcos:mapping:" }, "type": { - "const": "MappingSpec" + "const": "MappingSpec", + "description": "Discriminator constant \u2014 always \"MappingSpec\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "from": { "type": "object", @@ -40,7 +44,8 @@ "fieldPath": { "type": "string" } - } + }, + "description": "The source field endpoint: dataset URN and JSONPath field path." }, "to": { "type": "object", @@ -57,25 +62,29 @@ "fieldPath": { "type": "string" } - } + }, + "description": "The target field endpoint: dataset URN and JSONPath field path." }, "confidence": { "type": "number", "minimum": 0, - "maximum": 1 + "maximum": 1, + "description": "Aggregated mapping confidence score in the range [0, 1]." }, "evidence": { "type": "array", "items": { "$ref": "MappingEvidence.json" - } + }, + "description": "The list of evidence items that support this mapping confidence score." }, "state": { "enum": [ "proposed", "curated", "rejected" - ] + ], + "description": "Review state: proposed (unreviewed), curated (analyst-approved), or rejected." } } -} \ No newline at end of file +} diff --git a/schemas/MemoryEntry.json b/schemas/MemoryEntry.json index 8001cda..db7b638 100644 --- a/schemas/MemoryEntry.json +++ b/schemas/MemoryEntry.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/MemoryEntry.json", "title": "MemoryEntry", + "description": "A persistent agent memory of kind `rule` (standing instruction), `learned` (inferred from past sessions), or `recap` (post-session summary). Scoped to a workspace and path prefix list.", "type": "object", "additionalProperties": false, "required": [ @@ -19,41 +20,50 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:memory:" + "pattern": "^urn:srcos:memory:", + "description": "Stable URN identifier. Pattern: urn:srcos:memory:" }, "type": { - "const": "MemoryEntry" + "const": "MemoryEntry", + "description": "Discriminator constant \u2014 always \"MemoryEntry\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "kind": { "enum": [ "rule", "learned", "recap" - ] + ], + "description": "Memory type: rule (standing instruction that always applies), learned (inferred from past experience), or recap (end-of-session summary)." }, "namespace": { - "type": "string" + "type": "string", + "description": "Logical grouping for this memory (e.g. \"coding-standards\", \"user-preferences\")." }, "key": { - "type": "string" + "type": "string", + "description": "Unique key within the namespace for this memory entry." }, "payloadRef": { - "type": "string" + "type": "string", + "description": "Reference to the full memory content (file path, blob URI, or inline URN)." }, "authoritativeRef": { "type": [ "string", "null" - ] + ], + "description": "Optional reference to the authoritative source that this memory was derived from." }, "citationRefs": { "type": "array", "items": { "type": "string" - } + }, + "description": "References to sources that support or justify this memory." }, "scope": { "type": "object", @@ -82,7 +92,8 @@ ], "pattern": "^urn:srcos:session:" } - } + }, + "description": "The workspace and path prefixes this memory is relevant to." }, "freshness": { "type": "object", @@ -109,7 +120,8 @@ ], "minimum": 0 } - } + }, + "description": "When this memory was learned, optionally reviewed, and its time-to-live in seconds." } } } diff --git a/schemas/ObjectContext.json b/schemas/ObjectContext.json index 42d4424..16a1651 100644 --- a/schemas/ObjectContext.json +++ b/schemas/ObjectContext.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/ObjectContext.json", "title": "ObjectContext", + "description": "The access-control context for the object (resource) side of a PolicyDecision request. Carries the object's type, classification tags, zone, and arbitrary attributes.", "type": "object", "additionalProperties": false, "required": [ @@ -10,7 +11,8 @@ ], "properties": { "objectId": { - "type": "string" + "type": "string", + "description": "URN of the data object being accessed." }, "objectType": { "enum": [ @@ -21,23 +23,27 @@ "provenance", "schema", "agreement" - ] + ], + "description": "The type of the object: dataset, field, asset, run, provenance, schema, or agreement." }, "tags": { "type": "array", "items": { "type": "string" - } + }, + "description": "Classification tags currently applied to this object." }, "zone": { "type": [ "string", "null" - ] + ], + "description": "The data zone this object resides in (e.g. \"raw\", \"curated\", \"restricted\")." }, "attributes": { "type": "object", - "additionalProperties": true + "additionalProperties": true, + "description": "Arbitrary additional attributes for use in policy condition expressions." } } -} \ No newline at end of file +} diff --git a/schemas/ObjectSelector.json b/schemas/ObjectSelector.json index 242a563..a3e5cb7 100644 --- a/schemas/ObjectSelector.json +++ b/schemas/ObjectSelector.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/ObjectSelector.json", "title": "ObjectSelector", + "description": "A match clause used in a Policy scope to select which object types and attributes the policy applies to.", "type": "object", "additionalProperties": false, "required": [ @@ -18,11 +19,13 @@ "schema", "agreement", "any" - ] + ], + "description": "The object type this selector matches: dataset, field, asset, run, provenance, schema, agreement, or any." }, "match": { "type": "object", - "additionalProperties": true + "additionalProperties": true, + "description": "Attribute match criteria. Keys and values are defined by the policy engine implementation." } } -} \ No newline at end of file +} diff --git a/schemas/Obligation.json b/schemas/Obligation.json index c9c9645..527f218 100644 --- a/schemas/Obligation.json +++ b/schemas/Obligation.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/Obligation.json", "title": "Obligation", + "description": "An action that must be performed before (`pre`), after (`post`), or at runtime (`runtime`) as a condition of a permitted operation. Attached to PolicyDecisions and CapabilityTokens.", "type": "object", "additionalProperties": false, "required": [ @@ -17,18 +18,21 @@ "mask_fields", "aggregate_only", "attest_container" - ] + ], + "description": "The required action: obfuscate_before_export, log_access, retain_provenance, mask_fields, aggregate_only, or attest_container." }, "when": { "enum": [ "pre", "post", "runtime" - ] + ], + "description": "When the obligation must be fulfilled: pre (before the operation), post (after), or runtime (during)." }, "params": { "type": "object", - "additionalProperties": true + "additionalProperties": true, + "description": "Parameters for the obligation action (e.g. the workload URN to invoke for obfuscation)." } } -} \ No newline at end of file +} diff --git a/schemas/Party.json b/schemas/Party.json index 0d86381..3e70db8 100644 --- a/schemas/Party.json +++ b/schemas/Party.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/Party.json", "title": "Party", + "description": "A named signatory to an Agreement \u2014 a person, organisation, or service \u2014 with optional authority links to identity systems.", "type": "object", "additionalProperties": false, "required": [ @@ -12,23 +13,27 @@ "properties": { "partyId": { "type": "string", - "pattern": "^urn:srcos:party:" + "pattern": "^urn:srcos:party:", + "description": "Stable URN identifier. Pattern: urn:srcos:party:" }, "name": { - "type": "string" + "type": "string", + "description": "Human-readable name of the party (person, organisation, or service)." }, "kind": { "enum": [ "person", "org", "service" - ] + ], + "description": "Whether this party is a person, org (organisation), or service." }, "authorityLinks": { "type": "array", "items": { "$ref": "AuthorityLink.json" - } + }, + "description": "Links to identity entries for this party in external authority systems." } } -} \ No newline at end of file +} diff --git a/schemas/PhysicalAsset.json b/schemas/PhysicalAsset.json index 664cf54..13e232e 100644 --- a/schemas/PhysicalAsset.json +++ b/schemas/PhysicalAsset.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/PhysicalAsset.json", "title": "PhysicalAsset", + "description": "A specific physical resource reachable through a Connector: a table, bucket prefix, Kafka topic, or API endpoint.", "type": "object", "additionalProperties": false, "required": [ @@ -15,13 +16,16 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:asset:" + "pattern": "^urn:srcos:asset:", + "description": "Stable URN identifier. Pattern: urn:srcos:asset:" }, "type": { - "const": "PhysicalAsset" + "const": "PhysicalAsset", + "description": "Discriminator constant \u2014 always \"PhysicalAsset\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "assetKind": { "enum": [ @@ -31,14 +35,17 @@ "file", "api", "lakehouse" - ] + ], + "description": "The type of physical resource: objectStore, rdbms, stream, file, api, or lakehouse." }, "connectorId": { "type": "string", - "pattern": "^urn:srcos:connector:" + "pattern": "^urn:srcos:connector:", + "description": "URN of the Connector used to reach this asset. Pattern: urn:srcos:connector:" }, "location": { - "type": "string" + "type": "string", + "description": "The resource locator within the connector (e.g. S3 URI, table name, Kafka topic)." }, "identification": { "type": "object", @@ -68,7 +75,8 @@ "null" ] } - } + }, + "description": "Cloud-vendor identification metadata: vendor, account, region, and resource ID." } } -} \ No newline at end of file +} diff --git a/schemas/Policy.json b/schemas/Policy.json index bc80711..24e6e7e 100644 --- a/schemas/Policy.json +++ b/schemas/Policy.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/Policy.json", "title": "Policy", + "description": "An access-control policy. Combines a subject/object/purpose scope with permit/deny rules, pre/post obligations, and time-limited exceptions.", "type": "object", "additionalProperties": false, "required": [ @@ -16,16 +17,20 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:policy:" + "pattern": "^urn:srcos:policy:", + "description": "Stable URN identifier. Pattern: urn:srcos:policy:" }, "type": { - "const": "Policy" + "const": "Policy", + "description": "Discriminator constant \u2014 always \"Policy\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "name": { - "type": "string" + "type": "string", + "description": "Human-readable name of the policy." }, "scope": { "type": "object", @@ -54,25 +59,29 @@ "type": "string" } } - } + }, + "description": "Defines which subject kinds, object types, and purpose strings this policy applies to." }, "rules": { "type": "array", "items": { "$ref": "Rule.json" - } + }, + "description": "The ordered list of permit/deny rules evaluated against the scope." }, "obligations": { "type": "array", "items": { "$ref": "Obligation.json" - } + }, + "description": "Actions that must be performed whenever this policy permits access." }, "exceptions": { "type": "array", "items": { "$ref": "Exception.json" - } + }, + "description": "Time-limited exemptions that override the normal rules." } } -} \ No newline at end of file +} diff --git a/schemas/PolicyBinding.json b/schemas/PolicyBinding.json index c984a05..3d62548 100644 --- a/schemas/PolicyBinding.json +++ b/schemas/PolicyBinding.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/PolicyBinding.json", "title": "PolicyBinding", + "description": "Associates a Policy with a WorkflowSpec or SkillManifest, enforcing that policy for all runs of that workflow or invocations of that skill.", "type": "object", "additionalProperties": false, "required": [ @@ -11,11 +12,13 @@ "properties": { "policyId": { "type": "string", - "pattern": "^urn:srcos:policy:" + "pattern": "^urn:srcos:policy:", + "description": "URN of the Policy to enforce. Pattern: urn:srcos:policy:" }, "appliesTo": { "type": "object", - "additionalProperties": true + "additionalProperties": true, + "description": "Selector describing the resources or contexts to which this binding applies." } } -} \ No newline at end of file +} diff --git a/schemas/PolicyCondition.json b/schemas/PolicyCondition.json index e6f5d88..bb6914c 100644 --- a/schemas/PolicyCondition.json +++ b/schemas/PolicyCondition.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/PolicyCondition.json", "title": "PolicyCondition", + "description": "A rule-evaluation expression in one of four declared languages: jsonlogic, cel, rego, or cedar. Embedded inside a Rule.", "type": "object", "additionalProperties": false, "required": [ @@ -15,17 +16,20 @@ "cel", "rego", "cedar" - ] + ], + "description": "The expression language: jsonlogic (embeddable JSON rules), cel (Common Expression Language), rego (OPA Rego), or cedar (AWS Cedar)." }, "expr": { "type": "object", - "additionalProperties": true + "additionalProperties": true, + "description": "The condition expression. Structure is defined by the `language` value." }, "notes": { "type": [ "string", "null" - ] + ], + "description": "Optional human-readable notes explaining the condition logic." } } -} \ No newline at end of file +} diff --git a/schemas/PolicyDecision.json b/schemas/PolicyDecision.json index 84f9377..81bf8cd 100644 --- a/schemas/PolicyDecision.json +++ b/schemas/PolicyDecision.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/PolicyDecision.json", "title": "PolicyDecision", + "description": "The immutable, hash-signed audit record of a single /v2/decisions/evaluate call. Outcome is permit, deny, or permitWithObligations.", "type": "object", "additionalProperties": false, "required": [ @@ -18,24 +19,29 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:decision:" + "pattern": "^urn:srcos:decision:", + "description": "Stable URN identifier. Pattern: urn:srcos:decision:" }, "type": { - "const": "PolicyDecision" + "const": "PolicyDecision", + "description": "Discriminator constant \u2014 always \"PolicyDecision\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "decision": { "enum": [ "permit", "deny", "permitWithObligations" - ] + ], + "description": "The evaluation outcome: permit, deny, or permitWithObligations." }, "policyId": { "type": "string", - "pattern": "^urn:srcos:policy:" + "pattern": "^urn:srcos:policy:", + "description": "URN of the Policy that produced this decision. Pattern: urn:srcos:policy:" }, "inputs": { "type": "object", @@ -59,25 +65,30 @@ "type": "object", "additionalProperties": true } - } + }, + "description": "The exact subject, object, purpose, and environment inputs that were evaluated." }, "obligations": { "type": "array", "items": { "$ref": "Obligation.json" - } + }, + "description": "Obligations attached to a permitWithObligations decision." }, "issuedAt": { "type": "string", - "format": "date-time" + "format": "date-time", + "description": "ISO 8601 date-time when this decision was issued." }, "expiresAt": { "type": "string", - "format": "date-time" + "format": "date-time", + "description": "ISO 8601 date-time after which this decision is no longer valid." }, "decisionHash": { "type": "string", - "pattern": "^sha256:" + "pattern": "^sha256:", + "description": "sha256: prefixed hash of the canonical inputs+outcome for tamper-evidence." } } -} \ No newline at end of file +} diff --git a/schemas/ProfileStats.json b/schemas/ProfileStats.json index 8af5d18..6d1a341 100644 --- a/schemas/ProfileStats.json +++ b/schemas/ProfileStats.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/ProfileStats.json", "title": "ProfileStats", + "description": "Statistical summary of a dataset column: row count, null count, distinct count, top-N values, min, max, and observed string patterns.", "type": "object", "additionalProperties": false, "required": [ @@ -11,18 +12,21 @@ "properties": { "rowCount": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "Total number of rows in the profiled column." }, "nullCount": { "type": "integer", - "minimum": 0 + "minimum": 0, + "description": "Number of rows with a null value in this column." }, "distinctCount": { "type": [ "integer", "null" ], - "minimum": 0 + "minimum": 0, + "description": "Number of distinct non-null values (null if not computed)." }, "topValues": { "type": "array", @@ -42,27 +46,31 @@ "minimum": 0 } } - } + }, + "description": "The most frequent values and their counts, sorted descending by count." }, "min": { "type": [ "string", "number", "null" - ] + ], + "description": "Minimum observed value (as string or number depending on data type)." }, "max": { "type": [ "string", "number", "null" - ] + ], + "description": "Maximum observed value (as string or number depending on data type)." }, "patterns": { "type": "array", "items": { "type": "string" - } + }, + "description": "Regex or format patterns observed in string values (e.g. date formats, ID formats)." } } -} \ No newline at end of file +} diff --git a/schemas/ProvenanceRecord.json b/schemas/ProvenanceRecord.json index c157c02..f93ab82 100644 --- a/schemas/ProvenanceRecord.json +++ b/schemas/ProvenanceRecord.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/ProvenanceRecord.json", "title": "ProvenanceRecord", + "description": "A W3C PROV-compatible lineage record linking a RunRecord activity to its input and output data entities.", "type": "object", "additionalProperties": false, "required": [ @@ -16,13 +17,16 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:prov:" + "pattern": "^urn:srcos:prov:", + "description": "Stable URN identifier. Pattern: urn:srcos:prov:" }, "type": { - "const": "ProvenanceRecord" + "const": "ProvenanceRecord", + "description": "Discriminator constant \u2014 always \"ProvenanceRecord\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "activity": { "type": "string", @@ -60,17 +64,20 @@ "description": "sha256:..." } } - } + }, + "description": "The data entities consumed (role: input) and produced (role: output) by the activity." }, "createdAt": { "type": "string", - "format": "date-time" + "format": "date-time", + "description": "ISO 8601 date-time when this provenance record was created." }, "signature": { "type": [ "string", "null" - ] + ], + "description": "Optional cryptographic signature over the provenance record." } } -} \ No newline at end of file +} diff --git a/schemas/QualityMetric.json b/schemas/QualityMetric.json index 3111a05..2104c2e 100644 --- a/schemas/QualityMetric.json +++ b/schemas/QualityMetric.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/QualityMetric.json", "title": "QualityMetric", + "description": "A single named data quality dimension (completeness, validity, uniqueness, consistency, or timeliness) measured on a 0\u20131 scale.", "type": "object", "additionalProperties": false, "required": [ @@ -16,16 +17,19 @@ "uniqueness", "consistency", "timeliness" - ] + ], + "description": "The quality dimension: completeness, validity, uniqueness, consistency, or timeliness." }, "value": { "type": "number", "minimum": 0, - "maximum": 1 + "maximum": 1, + "description": "The measured score for this dimension, in the range [0, 1] (1 = perfect quality)." }, "details": { "type": "object", - "additionalProperties": true + "additionalProperties": true, + "description": "Optional dimension-specific detail object (e.g. invalidRows count for validity)." } } -} \ No newline at end of file +} diff --git a/schemas/Rating.json b/schemas/Rating.json index 068c2e2..819bad3 100644 --- a/schemas/Rating.json +++ b/schemas/Rating.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/Rating.json", "title": "Rating", + "description": "A 1\u20135 star rating attached to any addressable object, used to surface user-assessed data quality and usefulness.", "type": "object", "additionalProperties": false, "required": [ @@ -16,28 +17,35 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:rating:" + "pattern": "^urn:srcos:rating:", + "description": "Stable URN identifier. Pattern: urn:srcos:rating:" }, "type": { - "const": "Rating" + "const": "Rating", + "description": "Discriminator constant \u2014 always \"Rating\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "targetId": { - "type": "string" + "type": "string", + "description": "URN of the object being rated." }, "rater": { - "type": "string" + "type": "string", + "description": "URN of the subject who submitted this rating." }, "createdAt": { "type": "string", - "format": "date-time" + "format": "date-time", + "description": "ISO 8601 date-time when the rating was submitted." }, "value": { "type": "integer", "minimum": 1, - "maximum": 5 + "maximum": 5, + "description": "The star rating value, an integer in the range [1, 5]." } } -} \ No newline at end of file +} diff --git a/schemas/ReleaseReceipt.json b/schemas/ReleaseReceipt.json index 93d6d97..ebd7c95 100644 --- a/schemas/ReleaseReceipt.json +++ b/schemas/ReleaseReceipt.json @@ -2,18 +2,68 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/ReleaseReceipt.json", "title": "ReleaseReceipt", + "description": "A verified release record carrying artifact hashes, gate check results, and an overall release status for a specific release target.", "type": "object", "additionalProperties": false, - "required": ["id","type","specVersion","releaseTarget","verifiedAt","status"], + "required": [ + "id", + "type", + "specVersion", + "releaseTarget", + "verifiedAt", + "status" + ], "properties": { - "id": {"type": "string", "pattern": "^urn:srcos:release-receipt:"}, - "type": {"const": "ReleaseReceipt"}, - "specVersion": {"type": "string"}, - "releaseTarget": {"type": "string"}, - "sourceRef": {"type": ["string","null"]}, - "artifactHashes": {"type": "array", "items": {"type": "string"}}, - "checks": {"type": "array", "items": {"type": "string"}}, - "status": {"enum": ["verified","failed","partial"]}, - "verifiedAt": {"type": "string", "format": "date-time"} + "id": { + "type": "string", + "pattern": "^urn:srcos:release-receipt:", + "description": "Stable URN identifier. Pattern: urn:srcos:release-receipt:" + }, + "type": { + "const": "ReleaseReceipt", + "description": "Discriminator constant \u2014 always \"ReleaseReceipt\"." + }, + "specVersion": { + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." + }, + "releaseTarget": { + "type": "string", + "description": "The identifier of the release target (e.g. \"v2.0.0\", \"staging\", \"production\")." + }, + "sourceRef": { + "type": [ + "string", + "null" + ], + "description": "Optional reference to the source commit, tag, or artifact set." + }, + "artifactHashes": { + "type": "array", + "items": { + "type": "string" + }, + "description": "sha256: prefixed hashes of all artifacts included in this release." + }, + "checks": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Identifiers of the gate checks that were run (e.g. \"unit-tests\", \"schema-lint\", \"security-scan\")." + }, + "status": { + "enum": [ + "verified", + "failed", + "partial" + ], + "description": "Overall release status: verified (all checks passed), failed (at least one check failed), or partial." + }, + "verifiedAt": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 date-time when the release was verified." + } } } diff --git a/schemas/RolloutPolicy.json b/schemas/RolloutPolicy.json index 3353c05..47d954d 100644 --- a/schemas/RolloutPolicy.json +++ b/schemas/RolloutPolicy.json @@ -2,27 +2,75 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/RolloutPolicy.json", "title": "RolloutPolicy", + "description": "Audience-based percentage rollout rules for an ExperimentFlag. Controls which user segments see which flag state.", "type": "object", "additionalProperties": false, - "required": ["id","type","specVersion","flagRef","rules"], + "required": [ + "id", + "type", + "specVersion", + "flagRef", + "rules" + ], "properties": { - "id": {"type": "string", "pattern": "^urn:srcos:rollout:"}, - "type": {"const": "RolloutPolicy"}, - "specVersion": {"type": "string"}, - "flagRef": {"type": "string", "pattern": "^urn:srcos:flag:"}, + "id": { + "type": "string", + "pattern": "^urn:srcos:rollout:", + "description": "Stable URN identifier. Pattern: urn:srcos:rollout:" + }, + "type": { + "const": "RolloutPolicy", + "description": "Discriminator constant \u2014 always \"RolloutPolicy\"." + }, + "specVersion": { + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." + }, + "flagRef": { + "type": "string", + "pattern": "^urn:srcos:flag:", + "description": "URN of the ExperimentFlag this rollout policy controls. Pattern: urn:srcos:flag:" + }, "rules": { "type": "array", "items": { "type": "object", "additionalProperties": false, - "required": ["audience","state"], + "required": [ + "audience", + "state" + ], "properties": { - "audience": {"type": "string"}, - "state": {"enum": ["off","shadow","internal","beta","on"]}, - "percentage": {"type": ["number","null"], "minimum": 0, "maximum": 100} + "audience": { + "type": "string" + }, + "state": { + "enum": [ + "off", + "shadow", + "internal", + "beta", + "on" + ] + }, + "percentage": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 100 + } } - } + }, + "description": "Ordered list of audience-state-percentage rules. First matching rule wins." }, - "notes": {"type": ["string","null"]} + "notes": { + "type": [ + "string", + "null" + ], + "description": "Optional notes about the rollout strategy." + } } } diff --git a/schemas/Rule.json b/schemas/Rule.json index c838fc9..8de7091 100644 --- a/schemas/Rule.json +++ b/schemas/Rule.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/Rule.json", "title": "Rule", + "description": "A single permit or deny rule inside a Policy. Specifies the allowed operations and an optional typed PolicyCondition expression.", "type": "object", "additionalProperties": false, "required": [ @@ -13,7 +14,8 @@ "enum": [ "permit", "deny" - ] + ], + "description": "Whether this rule permits or denies the specified operations." }, "operations": { "type": "array", @@ -25,10 +27,12 @@ "transform", "share" ] - } + }, + "description": "The operations this rule applies to: read, write, export, transform, or share." }, "condition": { - "$ref": "PolicyCondition.json" + "$ref": "PolicyCondition.json", + "description": "Optional typed condition expression. If absent, the rule applies unconditionally." } } -} \ No newline at end of file +} diff --git a/schemas/RunRecord.json b/schemas/RunRecord.json index 7ef966f..c7a5f89 100644 --- a/schemas/RunRecord.json +++ b/schemas/RunRecord.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/RunRecord.json", "title": "RunRecord", + "description": "The audit record of a single workload execution. References the WorkloadSpec, DataSphere, input/output DataRefs, CapabilityToken, and ProvenanceRecord.", "type": "object", "additionalProperties": false, "required": [ @@ -19,40 +20,49 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:run:" + "pattern": "^urn:srcos:run:", + "description": "Stable URN identifier. Pattern: urn:srcos:run:" }, "type": { - "const": "RunRecord" + "const": "RunRecord", + "description": "Discriminator constant \u2014 always \"RunRecord\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "workload": { - "$ref": "WorkloadSpec.json" + "$ref": "WorkloadSpec.json", + "description": "The workload specification that was executed." }, "sphere": { - "$ref": "DataSphere.json" + "$ref": "DataSphere.json", + "description": "The data sphere (execution environment) in which the workload ran." }, "inputs": { "type": "array", "items": { "$ref": "DataRef.json" - } + }, + "description": "DataRefs describing the input data entities consumed by this run." }, "outputs": { "type": "array", "items": { "$ref": "DataRef.json" - } + }, + "description": "DataRefs describing the output data entities produced by this run." }, "tokenRef": { - "type": "string" + "type": "string", + "description": "Identifier of the CapabilityToken authorising this run." }, "decisionRef": { "type": [ "string", "null" - ] + ], + "description": "Optional URN of the PolicyDecision that authorised this run." }, "status": { "enum": [ @@ -60,7 +70,8 @@ "succeeded", "failed", "aborted" - ] + ], + "description": "Execution outcome: started, succeeded, failed, or aborted." }, "time": { "type": "object", @@ -80,14 +91,16 @@ ], "format": "date-time" } - } + }, + "description": "Run timing: startedAt (required) and optional endedAt." }, "provenanceRef": { "type": [ "string", "null" ], - "pattern": "^urn:srcos:prov:" + "pattern": "^urn:srcos:prov:", + "description": "Optional URN of the ProvenanceRecord capturing lineage for this run. Pattern: urn:srcos:prov:" }, "integrity": { "type": "object", @@ -117,7 +130,8 @@ "null" ] } - } + }, + "description": "Optional integrity hashes for inputs, outputs, and the run itself, plus an optional signature." } } -} \ No newline at end of file +} diff --git a/schemas/SchemaDefinition.json b/schemas/SchemaDefinition.json index a88b5ac..63c0e8f 100644 --- a/schemas/SchemaDefinition.json +++ b/schemas/SchemaDefinition.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/SchemaDefinition.json", "title": "SchemaDefinition", + "description": "A named, versioned logical schema composed of EntityFields. Referenced by a Dataset to describe its structure.", "type": "object", "additionalProperties": false, "required": [ @@ -14,34 +15,41 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:schema:" + "pattern": "^urn:srcos:schema:", + "description": "Stable URN identifier. Pattern: urn:srcos:schema:" }, "type": { - "const": "SchemaDefinition" + "const": "SchemaDefinition", + "description": "Discriminator constant \u2014 always \"SchemaDefinition\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "name": { - "type": "string" + "type": "string", + "description": "Human-readable name for this schema (e.g. \"health_obs_v1\")." }, "description": { "type": [ "string", "null" - ] + ], + "description": "Optional description of the schema's purpose and the entity it represents." }, "fields": { "type": "array", "items": { "$ref": "EntityField.json" - } + }, + "description": "The ordered list of EntityField descriptors that make up this schema." }, "links": { "type": "array", "items": { "$ref": "Link.json" - } + }, + "description": "Supplementary hyperlinks." } } -} \ No newline at end of file +} diff --git a/schemas/SessionReceipt.json b/schemas/SessionReceipt.json index 31685ab..9c67d3e 100644 --- a/schemas/SessionReceipt.json +++ b/schemas/SessionReceipt.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/SessionReceipt.json", "title": "SessionReceipt", + "description": "The final outcome record for a completed AgentSession. Records the terminal status, all produced artifacts, execution decisions, and gate results.", "type": "object", "additionalProperties": false, "required": [ @@ -18,17 +19,21 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:receipt:session:" + "pattern": "^urn:srcos:receipt:session:", + "description": "Stable URN identifier. Pattern: urn:srcos:receipt:session:" }, "type": { - "const": "SessionReceipt" + "const": "SessionReceipt", + "description": "Discriminator constant \u2014 always \"SessionReceipt\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "sessionRef": { "type": "string", - "pattern": "^urn:srcos:session:" + "pattern": "^urn:srcos:session:", + "description": "URN of the AgentSession this receipt summarises. Pattern: urn:srcos:session:" }, "status": { "enum": [ @@ -37,30 +42,35 @@ "paused", "deferred", "canceled" - ] + ], + "description": "Terminal status of the session: success, failure, paused, deferred, or canceled." }, "artifactRefs": { "type": "array", "items": { "type": "string" - } + }, + "description": "References to artifacts produced by the session (e.g. PRs, files, reports)." }, "decisionRefs": { "type": "array", "items": { "type": "string", "pattern": "^urn:srcos:exec-decision:" - } + }, + "description": "URNs of all ExecutionDecisions recorded during the session. Pattern: urn:srcos:exec-decision:" }, "gateResults": { "type": "array", "items": { "type": "string" - } + }, + "description": "Identifiers of post-session gate checks and their outcomes." }, "capturedAt": { "type": "string", - "format": "date-time" + "format": "date-time", + "description": "ISO 8601 date-time when this receipt was recorded." } } } diff --git a/schemas/SessionReview.json b/schemas/SessionReview.json index dbd93f0..ae157d7 100644 --- a/schemas/SessionReview.json +++ b/schemas/SessionReview.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/SessionReview.json", "title": "SessionReview", + "description": "A post-session learning review that summarises an AgentSession and links to the MemoryEntries extracted from it.", "type": "object", "additionalProperties": false, "required": [ @@ -14,13 +15,47 @@ "reviewedAt" ], "properties": { - "id": {"type": "string", "pattern": "^urn:srcos:session-review:"}, - "type": {"const": "SessionReview"}, - "specVersion": {"type": "string"}, - "sessionRef": {"type": "string", "pattern": "^urn:srcos:session:"}, - "summaryRef": {"type": "string"}, - "learnedMemoryRefs": {"type": "array", "items": {"type": "string", "pattern": "^urn:srcos:memory:"}}, - "followupRefs": {"type": "array", "items": {"type": "string"}}, - "reviewedAt": {"type": "string", "format": "date-time"} + "id": { + "type": "string", + "pattern": "^urn:srcos:session-review:", + "description": "Stable URN identifier. Pattern: urn:srcos:session-review:" + }, + "type": { + "const": "SessionReview", + "description": "Discriminator constant \u2014 always \"SessionReview\"." + }, + "specVersion": { + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." + }, + "sessionRef": { + "type": "string", + "pattern": "^urn:srcos:session:", + "description": "URN of the AgentSession being reviewed. Pattern: urn:srcos:session:" + }, + "summaryRef": { + "type": "string", + "description": "Reference to the summary artifact produced by this review." + }, + "learnedMemoryRefs": { + "type": "array", + "items": { + "type": "string", + "pattern": "^urn:srcos:memory:" + }, + "description": "URNs of MemoryEntries extracted and persisted from this session. Pattern: urn:srcos:memory:" + }, + "followupRefs": { + "type": "array", + "items": { + "type": "string" + }, + "description": "References to follow-up tasks or sessions spawned by this review." + }, + "reviewedAt": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 date-time when this review was conducted." + } } } diff --git a/schemas/SkillManifest.json b/schemas/SkillManifest.json index cee0455..c54bca2 100644 --- a/schemas/SkillManifest.json +++ b/schemas/SkillManifest.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/SkillManifest.json", "title": "SkillManifest", + "description": "A declared agent capability (skill) with activation rules, binary/tool requirements, policy bindings, expected artifact outputs, and safety settings.", "type": "object", "additionalProperties": false, "required": [ @@ -22,25 +23,32 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:skill:" + "pattern": "^urn:srcos:skill:", + "description": "Stable URN identifier. Pattern: urn:srcos:skill:" }, "type": { - "const": "SkillManifest" + "const": "SkillManifest", + "description": "Discriminator constant \u2014 always \"SkillManifest\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "name": { - "type": "string" + "type": "string", + "description": "Human-readable name of this skill (e.g. \"pdf-reader\", \"code-reviewer\")." }, "version": { - "type": "string" + "type": "string", + "description": "Semver version of this skill manifest." }, "entryDoc": { - "type": "string" + "type": "string", + "description": "Path or URN of the primary documentation or instruction file for this skill." }, "description": { - "type": "string" + "type": "string", + "description": "One-paragraph description of what this skill does and when to use it." }, "activationRules": { "type": "object", @@ -64,7 +72,8 @@ "type": "string" } } - } + }, + "description": "Conditions under which this skill should be automatically activated: slash commands, file patterns, or intent tags." }, "requires": { "type": "object", @@ -88,38 +97,45 @@ "type": "string" } } - } + }, + "description": "Runtime requirements: required binaries, any-of binaries, and required tool names." }, "executionSurfaceRef": { "type": [ "string", "null" ], - "pattern": "^urn:srcos:surface:" + "pattern": "^urn:srcos:surface:", + "description": "Optional URN of an ExecutionSurface override for this skill. Pattern: urn:srcos:surface:" }, "policyBindings": { "type": "array", "items": { "type": "string" - } + }, + "description": "Policy URNs that govern use of this skill." }, "artifactOutputs": { "type": "array", "items": { "type": "string" - } + }, + "description": "Identifiers of artifact types this skill is expected to produce." }, "reviewMode": { - "type": "boolean" + "type": "boolean", + "description": "When true, the skill operates in review-only mode and must not make changes." }, "allowShellExecution": { - "type": "boolean" + "type": "boolean", + "description": "Whether this skill is permitted to execute shell commands." }, "protectedPaths": { "type": "array", "items": { "type": "string" - } + }, + "description": "File system paths this skill must not access." } } } diff --git a/schemas/SubjectContext.json b/schemas/SubjectContext.json index 22b89c6..9b702f5 100644 --- a/schemas/SubjectContext.json +++ b/schemas/SubjectContext.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/SubjectContext.json", "title": "SubjectContext", + "description": "The access-control context for the subject (requester) side of a PolicyDecision request. Carries the subject's type, roles, and arbitrary attributes.", "type": "object", "additionalProperties": false, "required": [ @@ -10,7 +11,8 @@ ], "properties": { "subjectId": { - "type": "string" + "type": "string", + "description": "URN of the requesting subject (user, service, app, or workload)." }, "kind": { "enum": [ @@ -18,17 +20,20 @@ "service", "app", "workload" - ] + ], + "description": "The subject type: user, service, app, or workload." }, "roles": { "type": "array", "items": { "type": "string" - } + }, + "description": "Roles assigned to this subject in the current context." }, "attributes": { "type": "object", - "additionalProperties": true + "additionalProperties": true, + "description": "Arbitrary additional attributes for use in policy condition expressions." } } -} \ No newline at end of file +} diff --git a/schemas/SubjectSelector.json b/schemas/SubjectSelector.json index 0c6ab1e..fb44925 100644 --- a/schemas/SubjectSelector.json +++ b/schemas/SubjectSelector.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/SubjectSelector.json", "title": "SubjectSelector", + "description": "A match clause used in a Policy scope to select which subject kinds and attributes the policy applies to.", "type": "object", "additionalProperties": false, "required": [ @@ -15,11 +16,13 @@ "app", "workload", "any" - ] + ], + "description": "The subject kind this selector matches: user, service, app, workload, or any." }, "match": { "type": "object", - "additionalProperties": true + "additionalProperties": true, + "description": "Attribute match criteria. Keys and values are defined by the policy engine implementation." } } -} \ No newline at end of file +} diff --git a/schemas/TagAssignment.json b/schemas/TagAssignment.json index f1c0179..8455c7b 100644 --- a/schemas/TagAssignment.json +++ b/schemas/TagAssignment.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/TagAssignment.json", "title": "TagAssignment", + "description": "A classification tag attached to a field or glossary term, with a confidence score, source attribution, and optional human review record.", "type": "object", "additionalProperties": false, "required": [ @@ -12,19 +13,22 @@ ], "properties": { "tag": { - "type": "string" + "type": "string", + "description": "The classification tag identifier (e.g. \"pii.dob\", \"sensitive\", \"health\")." }, "state": { "enum": [ "inferred", "curated", "rejected" - ] + ], + "description": "Curation state: inferred (ML or rule-assigned, unreviewed), curated (analyst-confirmed), or rejected." }, "confidence": { "type": "number", "minimum": 0, - "maximum": 1 + "maximum": 1, + "description": "Confidence score for this tag assignment, in the range [0, 1]." }, "source": { "enum": [ @@ -32,13 +36,15 @@ "analyst", "rule", "import" - ] + ], + "description": "How the tag was assigned: ml (machine learning model), analyst (human review), rule (rule engine), or import (external system)." }, "evidence": { "type": "array", "items": { "type": "string" - } + }, + "description": "Human-readable notes or artifact identifiers supporting this tag assignment." }, "review": { "type": "object", @@ -63,7 +69,8 @@ "null" ] } - } + }, + "description": "Optional human review record: who reviewed, when, and their comment." } } -} \ No newline at end of file +} diff --git a/schemas/TelemetryEvent.json b/schemas/TelemetryEvent.json index af10c58..2e7be6b 100644 --- a/schemas/TelemetryEvent.json +++ b/schemas/TelemetryEvent.json @@ -2,16 +2,53 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/TelemetryEvent.json", "title": "TelemetryEvent", + "description": "A structured diagnostic or operational log event emitted during an AgentSession.", "type": "object", "additionalProperties": false, - "required": ["id","type","specVersion","sessionRef","eventType","capturedAt"], + "required": [ + "id", + "type", + "specVersion", + "sessionRef", + "eventType", + "capturedAt" + ], "properties": { - "id": {"type": "string", "pattern": "^urn:srcos:telemetry:"}, - "type": {"const": "TelemetryEvent"}, - "specVersion": {"type": "string"}, - "sessionRef": {"type": "string", "pattern": "^urn:srcos:session:"}, - "eventType": {"type": "string"}, - "severity": {"enum": ["debug","info","warn","error"]}, - "capturedAt": {"type": "string", "format": "date-time"} + "id": { + "type": "string", + "pattern": "^urn:srcos:telemetry:", + "description": "Stable URN identifier. Pattern: urn:srcos:telemetry:" + }, + "type": { + "const": "TelemetryEvent", + "description": "Discriminator constant \u2014 always \"TelemetryEvent\"." + }, + "specVersion": { + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." + }, + "sessionRef": { + "type": "string", + "pattern": "^urn:srcos:session:", + "description": "URN of the AgentSession that emitted this event. Pattern: urn:srcos:session:" + }, + "eventType": { + "type": "string", + "description": "Application-specific event type identifier (e.g. \"tool.invoked\", \"memory.loaded\", \"skill.activated\")." + }, + "severity": { + "enum": [ + "debug", + "info", + "warn", + "error" + ], + "description": "Log severity: debug, info, warn, or error." + }, + "capturedAt": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 date-time when this event was captured." + } } } diff --git a/schemas/Trigger.json b/schemas/Trigger.json index 8766673..67eb19a 100644 --- a/schemas/Trigger.json +++ b/schemas/Trigger.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/Trigger.json", "title": "Trigger", + "description": "Specifies how a WorkflowSpec is activated: on a cron schedule, in response to an event, or manually.", "type": "object", "additionalProperties": false, "required": [ @@ -13,19 +14,22 @@ "schedule", "event", "manual" - ] + ], + "description": "The trigger type: schedule (cron), event (reacts to an AsyncAPI channel message), or manual." }, "schedule": { "type": [ "string", "null" - ] + ], + "description": "Cron expression for schedule triggers (e.g. \"0 2 * * *\"). Required when kind is \"schedule\"." }, "eventType": { "type": [ "string", "null" - ] + ], + "description": "AsyncAPI event type string for event triggers. Required when kind is \"event\"." } } -} \ No newline at end of file +} diff --git a/schemas/ValidValues.json b/schemas/ValidValues.json index dbe87a2..c36e59f 100644 --- a/schemas/ValidValues.json +++ b/schemas/ValidValues.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/ValidValues.json", "title": "ValidValues", + "description": "A constraint on the acceptable values for an EntityField: an enumeration list, a numeric range, or a regex pattern.", "type": "object", "additionalProperties": false, "required": [ @@ -14,31 +15,36 @@ "enumeration", "range", "regex" - ] + ], + "description": "The constraint type: enumeration (fixed list), range (numeric min/max), or regex (pattern match)." }, "values": { "type": "array", "items": { "type": "string" - } + }, + "description": "The list of allowed values for enumeration constraints. Empty for range and regex constraints." }, "min": { "type": [ "number", "null" - ] + ], + "description": "Minimum allowed numeric value for range constraints. Null for other kinds." }, "max": { "type": [ "number", "null" - ] + ], + "description": "Maximum allowed numeric value for range constraints. Null for other kinds." }, "pattern": { "type": [ "string", "null" - ] + ], + "description": "Regular expression pattern for regex constraints. Null for other kinds." } } -} \ No newline at end of file +} diff --git a/schemas/WorkflowEdge.json b/schemas/WorkflowEdge.json index 374eeba..8f038fd 100644 --- a/schemas/WorkflowEdge.json +++ b/schemas/WorkflowEdge.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/WorkflowEdge.json", "title": "WorkflowEdge", + "description": "A directed dependency edge between two WorkflowNode IDs in a WorkflowSpec DAG.", "type": "object", "additionalProperties": false, "required": [ @@ -10,10 +11,12 @@ ], "properties": { "from": { - "type": "string" + "type": "string", + "description": "The `nodeId` of the upstream (source) WorkflowNode." }, "to": { - "type": "string" + "type": "string", + "description": "The `nodeId` of the downstream (target) WorkflowNode." } } -} \ No newline at end of file +} diff --git a/schemas/WorkflowNode.json b/schemas/WorkflowNode.json index 74f0a64..068f4b7 100644 --- a/schemas/WorkflowNode.json +++ b/schemas/WorkflowNode.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/WorkflowNode.json", "title": "WorkflowNode", + "description": "A single processing node in a WorkflowSpec DAG, wrapping a WorkloadSpec with input/output DataRefs, obligation requirements, and resource limits.", "type": "object", "additionalProperties": false, "required": [ @@ -12,28 +13,33 @@ ], "properties": { "nodeId": { - "type": "string" + "type": "string", + "description": "Unique identifier for this node within the WorkflowSpec DAG." }, "workload": { - "$ref": "WorkloadSpec.json" + "$ref": "WorkloadSpec.json", + "description": "The workload specification to execute at this node." }, "inputs": { "type": "array", "items": { "$ref": "DataRef.json" - } + }, + "description": "DataRefs describing the input data consumed by this node." }, "outputs": { "type": "array", "items": { "$ref": "DataRef.json" - } + }, + "description": "DataRefs describing the output data produced by this node." }, "requiredObligations": { "type": "array", "items": { "type": "string" - } + }, + "description": "Obligation names that must be fulfilled before this node may execute." }, "resources": { "type": "object", @@ -57,7 +63,8 @@ "null" ] } - } + }, + "description": "Optional resource request hints: CPU (e.g. \"2\"), memory (e.g. \"4Gi\"), and GPU count." } } -} \ No newline at end of file +} diff --git a/schemas/WorkflowSpec.json b/schemas/WorkflowSpec.json index 36014ec..d51fa41 100644 --- a/schemas/WorkflowSpec.json +++ b/schemas/WorkflowSpec.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/WorkflowSpec.json", "title": "WorkflowSpec", + "description": "A directed acyclic graph (DAG) of WorkflowNodes connected by WorkflowEdges, with triggers and policy bindings.", "type": "object", "additionalProperties": false, "required": [ @@ -15,40 +16,48 @@ "properties": { "id": { "type": "string", - "pattern": "^urn:srcos:workflow:" + "pattern": "^urn:srcos:workflow:", + "description": "Stable URN identifier. Pattern: urn:srcos:workflow:" }, "type": { - "const": "WorkflowSpec" + "const": "WorkflowSpec", + "description": "Discriminator constant \u2014 always \"WorkflowSpec\"." }, "specVersion": { - "type": "string" + "type": "string", + "description": "Spec version of this document, e.g. \"2.0.0\"." }, "name": { - "type": "string" + "type": "string", + "description": "Human-readable name of this workflow." }, "nodes": { "type": "array", "items": { "$ref": "WorkflowNode.json" - } + }, + "description": "The processing nodes of the DAG." }, "edges": { "type": "array", "items": { "$ref": "WorkflowEdge.json" - } + }, + "description": "The directed dependency edges connecting nodes in the DAG." }, "triggers": { "type": "array", "items": { "$ref": "Trigger.json" - } + }, + "description": "How this workflow is activated (schedule, event, or manual)." }, "policyBindings": { "type": "array", "items": { "$ref": "PolicyBinding.json" - } + }, + "description": "Policies that must be satisfied before this workflow may execute." } } -} \ No newline at end of file +} diff --git a/schemas/WorkloadSpec.json b/schemas/WorkloadSpec.json index 418dfed..de5502c 100644 --- a/schemas/WorkloadSpec.json +++ b/schemas/WorkloadSpec.json @@ -2,6 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.srcos.ai/v2/WorkloadSpec.json", "title": "WorkloadSpec", + "description": "A runnable workload specification: a container image, Spark job, serverless function, or stream processor with its entry point and parameters.", "type": "object", "additionalProperties": false, "required": [ @@ -13,7 +14,8 @@ "properties": { "workloadId": { "type": "string", - "pattern": "^urn:srcos:workload:" + "pattern": "^urn:srcos:workload:", + "description": "Stable URN identifier. Pattern: urn:srcos:workload:" }, "kind": { "enum": [ @@ -21,17 +23,21 @@ "container", "function", "streamProcessor" - ] + ], + "description": "The execution model: sparkJob, container, function (serverless), or streamProcessor." }, "image": { - "type": "string" + "type": "string", + "description": "Container image reference or function ARN (e.g. \"ghcr.io/org/image:tag\")." }, "entrypoint": { - "type": "string" + "type": "string", + "description": "The command or function handler to invoke (e.g. \"obfuscate\", \"handler.main\")." }, "params": { "type": "object", - "additionalProperties": true + "additionalProperties": true, + "description": "Arbitrary execution parameters passed to the workload at runtime." } } -} \ No newline at end of file +} From 6e997ea61eee9ec7410740d463f62911b6b4f056 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 17:28:43 +0000 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20Phase=204+5=20=E2=80=93=20add=20mis?= =?UTF-8?q?sing=20examples=20and=20expand=20semantic=20overlay?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agent-Logs-Url: https://github.com/SourceOS-Linux/sourceos-spec/sessions/8b9ff02b-0b12-4bf8-8f38-efe8f63363c9 Co-authored-by: mdheller <21163552+mdheller@users.noreply.github.com> --- examples/agentsession.json | 34 +++++ examples/capabilitytoken.json | 29 ++++ examples/community.json | 15 ++ examples/datasphere.json | 14 ++ examples/executiondecision.json | 15 ++ examples/experimentflag.json | 10 ++ examples/frustration.json | 9 ++ examples/memory.json | 21 +++ examples/rating.json | 9 ++ examples/releasereceipt.json | 13 ++ examples/rolloutpolicy.json | 24 ++++ examples/sessionreceipt.json | 11 ++ examples/sessionreview.json | 10 ++ examples/skillmanifest.json | 25 ++++ examples/telemetry.json | 9 ++ examples/workflow.json | 53 +++++++ semantic/context.jsonld | 62 ++++++++- semantic/hydra.jsonld | 235 ++++++++++++++++++++++++++++++-- 18 files changed, 579 insertions(+), 19 deletions(-) create mode 100644 examples/agentsession.json create mode 100644 examples/capabilitytoken.json create mode 100644 examples/community.json create mode 100644 examples/datasphere.json create mode 100644 examples/executiondecision.json create mode 100644 examples/experimentflag.json create mode 100644 examples/frustration.json create mode 100644 examples/memory.json create mode 100644 examples/rating.json create mode 100644 examples/releasereceipt.json create mode 100644 examples/rolloutpolicy.json create mode 100644 examples/sessionreceipt.json create mode 100644 examples/sessionreview.json create mode 100644 examples/skillmanifest.json create mode 100644 examples/telemetry.json create mode 100644 examples/workflow.json diff --git a/examples/agentsession.json b/examples/agentsession.json new file mode 100644 index 0000000..44e0ed0 --- /dev/null +++ b/examples/agentsession.json @@ -0,0 +1,34 @@ +{ + "id": "urn:srcos:session:s001", + "type": "AgentSession", + "specVersion": "2.0.0", + "role": "executor", + "status": "completed", + "mode": "execute", + "workspaceRef": "workspace:sourceos-local", + "worktreeRef": null, + "substrate": "local", + "surface": { + "pty": true, + "workdir": "/home/runner/work/sourceos-spec", + "background": false, + "reviewOnly": false, + "worktreeStrategy": "none", + "sandboxMode": "user", + "networkMode": "allowlist", + "egressAllowlist": ["api.github.com", "*.srcos.ai"], + "elevated": false, + "protectedPaths": [".git/config", ".env"], + "approvalProfile": null + }, + "provider": "openai", + "skillRefs": ["urn:srcos:skill:obfuscation-runner"], + "memoryRefs": ["urn:srcos:memory:m001"], + "transcriptRef": null, + "decisionRefs": ["urn:srcos:exec-decision:ed001"], + "telemetryRefs": ["urn:srcos:telemetry:t001"], + "time": { + "startedAt": "2025-12-24T05:00:00Z", + "endedAt": "2025-12-24T05:10:00Z" + } +} diff --git a/examples/capabilitytoken.json b/examples/capabilitytoken.json new file mode 100644 index 0000000..2574bd6 --- /dev/null +++ b/examples/capabilitytoken.json @@ -0,0 +1,29 @@ +{ + "tokenId": "tok_123", + "subject": { + "subjectId": "urn:srcos:subject:user:me", + "kind": "user", + "roles": ["owner"], + "attributes": {} + }, + "scope": { + "datasetIds": ["urn:srcos:dataset:health_obs"], + "fieldPaths": ["$.patient.dateOfBirth"], + "assetIds": ["urn:srcos:asset:lake_curated_health"], + "operations": ["read", "export"] + }, + "purpose": "export", + "decisionRef": "urn:srcos:decision:aa11bb22", + "obligations": [ + { + "name": "obfuscate_before_export", + "when": "pre", + "params": { + "workload": "urn:srcos:workload:obfuscator_v1" + } + } + ], + "iat": 1735016400, + "exp": 1735020000, + "signature": "sig_dummy" +} diff --git a/examples/community.json b/examples/community.json new file mode 100644 index 0000000..48a4876 --- /dev/null +++ b/examples/community.json @@ -0,0 +1,15 @@ +{ + "id": "urn:srcos:community:data-governance-team", + "type": "Community", + "specVersion": "2.0.0", + "name": "Data Governance Team", + "description": "The team responsible for reviewing and curating classification tags, glossary terms, and data agreements.", + "members": [ + "urn:srcos:subject:user:me", + "urn:srcos:subject:user:alice", + "urn:srcos:subject:user:bob" + ], + "links": [ + {"rel": "self", "href": "https://api.srcos.local/v2/communities/data-governance-team", "type": "application/json"} + ] +} diff --git a/examples/datasphere.json b/examples/datasphere.json new file mode 100644 index 0000000..20df4eb --- /dev/null +++ b/examples/datasphere.json @@ -0,0 +1,14 @@ +{ + "sphereId": "urn:srcos:sphere:personal_curated", + "name": "Personal Curated Sphere", + "boundary": { + "zone": "curated", + "networkPolicy": null, + "storagePolicy": null + }, + "controls": { + "accessEnforcer": "enforcer.v2", + "provenance": "hashes", + "containerAttestation": "basic" + } +} diff --git a/examples/executiondecision.json b/examples/executiondecision.json new file mode 100644 index 0000000..d316a0f --- /dev/null +++ b/examples/executiondecision.json @@ -0,0 +1,15 @@ +{ + "id": "urn:srcos:exec-decision:ed001", + "type": "ExecutionDecision", + "specVersion": "2.0.0", + "sessionRef": "urn:srcos:session:s001", + "toolRequestRef": null, + "decision": "allow", + "reason": "Tool invocation is within the approved scope of the active CapabilityToken and no protected paths are affected.", + "updatedInput": null, + "policyRef": "urn:srcos:policy:export_health_restricted", + "obligations": ["log_access", "retain_provenance"], + "issuedAt": "2025-12-24T05:00:05Z", + "expiresAt": "2025-12-24T06:00:05Z", + "decisionHash": "sha256:a3f2c1e8d4b9a7f6c2e1d8b4a9f7c3e2d1b8a5f4c3e2d1b8a5f4c3e2d1b8a5f4" +} diff --git a/examples/experimentflag.json b/examples/experimentflag.json new file mode 100644 index 0000000..e42d770 --- /dev/null +++ b/examples/experimentflag.json @@ -0,0 +1,10 @@ +{ + "id": "urn:srcos:flag:new-obfuscation-algorithm", + "type": "ExperimentFlag", + "specVersion": "2.0.0", + "name": "new-obfuscation-algorithm", + "state": "beta", + "owner": "urn:srcos:subject:user:me", + "description": "Enables the next-generation k-anonymisation algorithm with improved performance for large datasets.", + "killSwitch": false +} diff --git a/examples/frustration.json b/examples/frustration.json new file mode 100644 index 0000000..69b1e52 --- /dev/null +++ b/examples/frustration.json @@ -0,0 +1,9 @@ +{ + "id": "urn:srcos:frustration:f001", + "type": "FrustrationSignal", + "specVersion": "2.0.0", + "sessionRef": "urn:srcos:session:s001", + "signal": "repeated-failure", + "count": 3, + "capturedAt": "2025-12-24T05:05:00Z" +} diff --git a/examples/memory.json b/examples/memory.json new file mode 100644 index 0000000..bfd4c8d --- /dev/null +++ b/examples/memory.json @@ -0,0 +1,21 @@ +{ + "id": "urn:srcos:memory:m001", + "type": "MemoryEntry", + "specVersion": "2.0.0", + "kind": "learned", + "namespace": "obfuscation-preferences", + "key": "k-anon-default-k", + "payloadRef": "blob://memory/m001-payload.json", + "authoritativeRef": null, + "citationRefs": ["urn:srcos:session:s001"], + "scope": { + "workspace": "workspace:sourceos-local", + "pathPrefixes": ["schemas/", "examples/"], + "sessionRef": "urn:srcos:session:s001" + }, + "freshness": { + "learnedAt": "2025-12-24T05:10:00Z", + "reviewedAt": null, + "ttl": 2592000 + } +} diff --git a/examples/rating.json b/examples/rating.json new file mode 100644 index 0000000..27b35ff --- /dev/null +++ b/examples/rating.json @@ -0,0 +1,9 @@ +{ + "id": "urn:srcos:rating:rate001", + "type": "Rating", + "specVersion": "2.0.0", + "targetId": "urn:srcos:dataset:health_obs", + "rater": "urn:srcos:subject:user:me", + "createdAt": "2025-12-24T05:00:00Z", + "value": 5 +} diff --git a/examples/releasereceipt.json b/examples/releasereceipt.json new file mode 100644 index 0000000..8a9438f --- /dev/null +++ b/examples/releasereceipt.json @@ -0,0 +1,13 @@ +{ + "id": "urn:srcos:release-receipt:v2.0.0", + "type": "ReleaseReceipt", + "specVersion": "2.0.0", + "releaseTarget": "v2.0.0", + "sourceRef": "git:SourceOS-Linux/sourceos-spec@abc123", + "artifactHashes": [ + "sha256:054282cdcbac6f6b791aba2fd011b4e44f18bcc6e1dd2c63a872c314a818d5ec" + ], + "checks": ["schema-lint", "example-validation", "openapi-lint"], + "status": "verified", + "verifiedAt": "2025-12-24T05:20:00Z" +} diff --git a/examples/rolloutpolicy.json b/examples/rolloutpolicy.json new file mode 100644 index 0000000..7cedb51 --- /dev/null +++ b/examples/rolloutpolicy.json @@ -0,0 +1,24 @@ +{ + "id": "urn:srcos:rollout:rp001", + "type": "RolloutPolicy", + "specVersion": "2.0.0", + "flagRef": "urn:srcos:flag:new-obfuscation-algorithm", + "rules": [ + { + "audience": "internal-staff", + "state": "on", + "percentage": null + }, + { + "audience": "beta-testers", + "state": "beta", + "percentage": 50.0 + }, + { + "audience": "everyone", + "state": "off", + "percentage": null + } + ], + "notes": "Graduating the new algorithm: internal first, then 50% beta, then GA." +} diff --git a/examples/sessionreceipt.json b/examples/sessionreceipt.json new file mode 100644 index 0000000..7fcf475 --- /dev/null +++ b/examples/sessionreceipt.json @@ -0,0 +1,11 @@ +{ + "id": "urn:srcos:receipt:session:r001", + "type": "SessionReceipt", + "specVersion": "2.0.0", + "sessionRef": "urn:srcos:session:s001", + "status": "success", + "artifactRefs": ["pr://github.com/SourceOS-Linux/sourceos-spec/pulls/1"], + "decisionRefs": ["urn:srcos:exec-decision:ed001"], + "gateResults": ["unit-tests:passed", "schema-lint:passed"], + "capturedAt": "2025-12-24T05:10:00Z" +} diff --git a/examples/sessionreview.json b/examples/sessionreview.json new file mode 100644 index 0000000..09b094e --- /dev/null +++ b/examples/sessionreview.json @@ -0,0 +1,10 @@ +{ + "id": "urn:srcos:session-review:sr001", + "type": "SessionReview", + "specVersion": "2.0.0", + "sessionRef": "urn:srcos:session:s001", + "summaryRef": "blob://summaries/s001-summary.md", + "learnedMemoryRefs": ["urn:srcos:memory:m001"], + "followupRefs": [], + "reviewedAt": "2025-12-24T05:15:00Z" +} diff --git a/examples/skillmanifest.json b/examples/skillmanifest.json new file mode 100644 index 0000000..4a4ecb2 --- /dev/null +++ b/examples/skillmanifest.json @@ -0,0 +1,25 @@ +{ + "id": "urn:srcos:skill:obfuscation-runner", + "type": "SkillManifest", + "specVersion": "2.0.0", + "name": "obfuscation-runner", + "version": "1.0.0", + "entryDoc": "skills/obfuscation-runner/README.md", + "description": "Runs the k-anonymisation obfuscation workload on a health dataset before export. Validates the active CapabilityToken, launches the obfuscator container, and records provenance.", + "activationRules": { + "commands": ["obfuscate", "run-obfuscator"], + "filePatterns": ["**/obfuscation-config.yaml"], + "intentTags": ["data-obfuscation", "privacy-export"] + }, + "requires": { + "binaries": ["docker"], + "anyBins": [], + "tools": ["bash"] + }, + "executionSurfaceRef": null, + "policyBindings": ["urn:srcos:policy:export_health_restricted"], + "artifactOutputs": ["run-record", "provenance-record"], + "reviewMode": false, + "allowShellExecution": true, + "protectedPaths": [".env", "*.key"] +} diff --git a/examples/telemetry.json b/examples/telemetry.json new file mode 100644 index 0000000..790c56d --- /dev/null +++ b/examples/telemetry.json @@ -0,0 +1,9 @@ +{ + "id": "urn:srcos:telemetry:t001", + "type": "TelemetryEvent", + "specVersion": "2.0.0", + "sessionRef": "urn:srcos:session:s001", + "eventType": "tool.invoked", + "severity": "info", + "capturedAt": "2025-12-24T05:00:05Z" +} diff --git a/examples/workflow.json b/examples/workflow.json new file mode 100644 index 0000000..9a59316 --- /dev/null +++ b/examples/workflow.json @@ -0,0 +1,53 @@ +{ + "id": "urn:srcos:workflow:etl_health_obfuscation_v1", + "type": "WorkflowSpec", + "specVersion": "2.0.0", + "name": "Health Obfuscation ETL Workflow", + "nodes": [ + { + "nodeId": "ingest", + "workload": { + "workloadId": "urn:srcos:workload:ingestor_v1", + "kind": "container", + "image": "ghcr.io/srcos/ingestor:v1", + "entrypoint": "ingest", + "params": {"source": "raw"} + }, + "inputs": [ + {"refType": "asset", "id": "urn:srcos:asset:lake_curated_health", "fieldPaths": []} + ], + "outputs": [ + {"refType": "dataset", "id": "urn:srcos:dataset:health_obs", "fieldPaths": []} + ], + "requiredObligations": [], + "resources": {"cpu": "1", "memory": "2Gi", "gpu": null} + }, + { + "nodeId": "obfuscate", + "workload": { + "workloadId": "urn:srcos:workload:obfuscator_v1", + "kind": "container", + "image": "ghcr.io/srcos/obfuscator:v1", + "entrypoint": "obfuscate", + "params": {"mode": "k-anon", "k": 5} + }, + "inputs": [ + {"refType": "dataset", "id": "urn:srcos:dataset:health_obs", "fieldPaths": ["$.patient.dateOfBirth"]} + ], + "outputs": [ + {"refType": "dataset", "id": "urn:srcos:dataset:obfuscated_out", "fieldPaths": []} + ], + "requiredObligations": ["obfuscate_before_export"], + "resources": {"cpu": "2", "memory": "4Gi", "gpu": null} + } + ], + "edges": [ + {"from": "ingest", "to": "obfuscate"} + ], + "triggers": [ + {"kind": "schedule", "schedule": "0 2 * * *", "eventType": null} + ], + "policyBindings": [ + {"policyId": "urn:srcos:policy:export_health_restricted", "appliesTo": {}} + ] +} diff --git a/semantic/context.jsonld b/semantic/context.jsonld index 09e11b1..7d86a32 100644 --- a/semantic/context.jsonld +++ b/semantic/context.jsonld @@ -3,14 +3,68 @@ "srcos": "https://schemas.srcos.ai/v2/", "hydra": "http://www.w3.org/ns/hydra/core#", "prov": "http://www.w3.org/ns/prov#", + "schema": "https://schema.org/", "id": "@id", "type": "@type", + + "AgentSession": "srcos:AgentSession", + "Agreement": "srcos:Agreement", + "AuthorityLink": "srcos:AuthorityLink", + "CapabilityToken": "srcos:CapabilityToken", + "Comment": "srcos:Comment", + "Community": "srcos:Community", + "Connector": "srcos:Connector", + "DataRef": "srcos:DataRef", + "DataSphere": "srcos:DataSphere", "Dataset": "srcos:Dataset", + "EntityField": "srcos:EntityField", + "EventEnvelope": "srcos:EventEnvelope", + "Exception": "srcos:Exception", + "ExecutionDecision": "srcos:ExecutionDecision", + "ExecutionSurface": "srcos:ExecutionSurface", + "ExperimentFlag": "srcos:ExperimentFlag", "Field": "srcos:Field", + "FrustrationSignal": "srcos:FrustrationSignal", + "GlossaryTerm": "srcos:GlossaryTerm", + "Link": "srcos:Link", + "MappingEvidence": "srcos:MappingEvidence", + "MappingSpec": "srcos:MappingSpec", + "MemoryEntry": "srcos:MemoryEntry", + "ObjectContext": "srcos:ObjectContext", + "ObjectSelector": "srcos:ObjectSelector", + "Obligation": "srcos:Obligation", + "Party": "srcos:Party", + "PhysicalAsset": "srcos:PhysicalAsset", "Policy": "srcos:Policy", - "WorkflowSpec": "srcos:WorkflowSpec", + "PolicyBinding": "srcos:PolicyBinding", + "PolicyCondition": "srcos:PolicyCondition", + "PolicyDecision": "srcos:PolicyDecision", + "ProfileStats": "srcos:ProfileStats", + "ProvenanceRecord": "srcos:ProvenanceRecord", + "QualityMetric": "srcos:QualityMetric", + "Rating": "srcos:Rating", + "ReleaseReceipt": "srcos:ReleaseReceipt", + "RolloutPolicy": "srcos:RolloutPolicy", + "Rule": "srcos:Rule", "RunRecord": "srcos:RunRecord", - "Agreement": "srcos:Agreement", - "GlossaryTerm": "srcos:GlossaryTerm" + "SchemaDefinition": "srcos:SchemaDefinition", + "SessionReceipt": "srcos:SessionReceipt", + "SessionReview": "srcos:SessionReview", + "SkillManifest": "srcos:SkillManifest", + "SubjectContext": "srcos:SubjectContext", + "SubjectSelector": "srcos:SubjectSelector", + "TagAssignment": "srcos:TagAssignment", + "TelemetryEvent": "srcos:TelemetryEvent", + "Trigger": "srcos:Trigger", + "ValidValues": "srcos:ValidValues", + "WorkflowEdge": "srcos:WorkflowEdge", + "WorkflowNode": "srcos:WorkflowNode", + "WorkflowSpec": "srcos:WorkflowSpec", + "WorkloadSpec": "srcos:WorkloadSpec", + + "wasGeneratedBy": { "@id": "prov:wasGeneratedBy", "@type": "@id" }, + "used": { "@id": "prov:used", "@type": "@id" }, + "wasAssociatedWith": { "@id": "prov:wasAssociatedWith", "@type": "@id" }, + "wasDerivedFrom": { "@id": "prov:wasDerivedFrom", "@type": "@id" } } -} \ No newline at end of file +} diff --git a/semantic/hydra.jsonld b/semantic/hydra.jsonld index b99b2c1..cb04800 100644 --- a/semantic/hydra.jsonld +++ b/semantic/hydra.jsonld @@ -3,40 +3,245 @@ "srcos": "https://schemas.srcos.ai/v2/", "hydra": "http://www.w3.org/ns/hydra/core#", "prov": "http://www.w3.org/ns/prov#", + "schema": "https://schema.org/", "id": "@id", "type": "@type", + + "AgentSession": "srcos:AgentSession", + "Agreement": "srcos:Agreement", + "AuthorityLink": "srcos:AuthorityLink", + "CapabilityToken": "srcos:CapabilityToken", + "Comment": "srcos:Comment", + "Community": "srcos:Community", + "Connector": "srcos:Connector", + "DataRef": "srcos:DataRef", + "DataSphere": "srcos:DataSphere", "Dataset": "srcos:Dataset", + "EntityField": "srcos:EntityField", + "EventEnvelope": "srcos:EventEnvelope", + "Exception": "srcos:Exception", + "ExecutionDecision": "srcos:ExecutionDecision", + "ExecutionSurface": "srcos:ExecutionSurface", + "ExperimentFlag": "srcos:ExperimentFlag", "Field": "srcos:Field", + "FrustrationSignal": "srcos:FrustrationSignal", + "GlossaryTerm": "srcos:GlossaryTerm", + "Link": "srcos:Link", + "MappingEvidence": "srcos:MappingEvidence", + "MappingSpec": "srcos:MappingSpec", + "MemoryEntry": "srcos:MemoryEntry", + "ObjectContext": "srcos:ObjectContext", + "ObjectSelector": "srcos:ObjectSelector", + "Obligation": "srcos:Obligation", + "Party": "srcos:Party", + "PhysicalAsset": "srcos:PhysicalAsset", "Policy": "srcos:Policy", - "WorkflowSpec": "srcos:WorkflowSpec", + "PolicyBinding": "srcos:PolicyBinding", + "PolicyCondition": "srcos:PolicyCondition", + "PolicyDecision": "srcos:PolicyDecision", + "ProfileStats": "srcos:ProfileStats", + "ProvenanceRecord": "srcos:ProvenanceRecord", + "QualityMetric": "srcos:QualityMetric", + "Rating": "srcos:Rating", + "ReleaseReceipt": "srcos:ReleaseReceipt", + "RolloutPolicy": "srcos:RolloutPolicy", + "Rule": "srcos:Rule", "RunRecord": "srcos:RunRecord", - "Agreement": "srcos:Agreement", - "GlossaryTerm": "srcos:GlossaryTerm" + "SchemaDefinition": "srcos:SchemaDefinition", + "SessionReceipt": "srcos:SessionReceipt", + "SessionReview": "srcos:SessionReview", + "SkillManifest": "srcos:SkillManifest", + "SubjectContext": "srcos:SubjectContext", + "SubjectSelector": "srcos:SubjectSelector", + "TagAssignment": "srcos:TagAssignment", + "TelemetryEvent": "srcos:TelemetryEvent", + "Trigger": "srcos:Trigger", + "ValidValues": "srcos:ValidValues", + "WorkflowEdge": "srcos:WorkflowEdge", + "WorkflowNode": "srcos:WorkflowNode", + "WorkflowSpec": "srcos:WorkflowSpec", + "WorkloadSpec": "srcos:WorkloadSpec", + + "wasGeneratedBy": { "@id": "prov:wasGeneratedBy", "@type": "@id" }, + "used": { "@id": "prov:used", "@type": "@id" }, + "wasAssociatedWith": { "@id": "prov:wasAssociatedWith", "@type": "@id" }, + "wasDerivedFrom": { "@id": "prov:wasDerivedFrom", "@type": "@id" } }, "@id": "https://api.srcos.local/v2", "@type": "hydra:ApiDocumentation", - "hydra:title": "SourceOS/SociOS Metadata Plane API (v2)", + "hydra:title": "SourceOS/SociOS API (v2)", + "hydra:description": "The SourceOS/SociOS Metadata Plane and Agent Plane API, providing governance-gated access to datasets, policies, provenance, and agent session management.", "hydra:entrypoint": "https://api.srcos.local/v2", "hydra:supportedClass": [ + { + "@id": "srcos:Connector", + "hydra:title": "Connector", + "hydra:description": "A named, typed connection configuration for a physical data store.", + "hydra:supportedOperation": [ + { "hydra:method": "POST", "hydra:title": "upsertConnector", "hydra:description": "Creates or updates a Connector." } + ] + }, + { + "@id": "srcos:PhysicalAsset", + "hydra:title": "PhysicalAsset", + "hydra:description": "A specific physical resource reachable through a Connector.", + "hydra:supportedOperation": [ + { "hydra:method": "POST", "hydra:title": "upsertPhysicalAsset", "hydra:description": "Creates or updates a PhysicalAsset." } + ] + }, + { + "@id": "srcos:SchemaDefinition", + "hydra:title": "SchemaDefinition", + "hydra:description": "A named, versioned logical schema composed of EntityFields.", + "hydra:supportedOperation": [ + { "hydra:method": "POST", "hydra:title": "upsertSchemaDefinition", "hydra:description": "Creates or updates a SchemaDefinition." } + ] + }, + { + "@id": "srcos:Agreement", + "hydra:title": "Agreement", + "hydra:description": "A data-sharing agreement between one or more parties.", + "hydra:supportedOperation": [ + { "hydra:method": "POST", "hydra:title": "upsertAgreement", "hydra:description": "Creates or updates an Agreement." } + ] + }, + { + "@id": "srcos:GlossaryTerm", + "hydra:title": "GlossaryTerm", + "hydra:description": "A defined business glossary term with synonyms and authority links.", + "hydra:supportedOperation": [ + { "hydra:method": "POST", "hydra:title": "upsertGlossaryTerm", "hydra:description": "Creates or updates a GlossaryTerm." } + ] + }, { "@id": "srcos:Dataset", + "hydra:title": "Dataset", + "hydra:description": "A governance-annotated logical view of a PhysicalAsset.", + "hydra:supportedOperation": [ + { "hydra:method": "GET", "hydra:title": "getDataset", "hydra:description": "Retrieves a Dataset by URN." }, + { "hydra:method": "POST", "hydra:title": "upsertDataset", "hydra:description": "Creates or updates a Dataset." } + ] + }, + { + "@id": "srcos:Field", + "hydra:title": "Field", + "hydra:description": "A fully annotated, quality-profiled field bound to a Dataset.", + "hydra:supportedOperation": [ + { "hydra:method": "POST", "hydra:title": "upsertField", "hydra:description": "Creates or updates a Field." } + ] + }, + { + "@id": "srcos:MappingSpec", + "hydra:title": "MappingSpec", + "hydra:description": "A field-to-field semantic mapping with confidence evidence.", "hydra:supportedOperation": [ - { - "hydra:method": "GET" - }, - { - "hydra:method": "POST" - } + { "hydra:method": "POST", "hydra:title": "upsertMapping", "hydra:description": "Creates or updates a MappingSpec." } ] }, { "@id": "srcos:Policy", + "hydra:title": "Policy", + "hydra:description": "An access-control policy with subject/object/purpose scope and rules.", + "hydra:supportedOperation": [ + { "hydra:method": "POST", "hydra:title": "upsertPolicy", "hydra:description": "Creates or updates a Policy." }, + { "hydra:method": "POST", "hydra:title": "evaluatePolicy", "hydra:description": "Evaluates a PolicyDecision for a given subject/object/purpose triple." } + ] + }, + { + "@id": "srcos:PolicyDecision", + "hydra:title": "PolicyDecision", + "hydra:description": "The immutable audit record of a policy evaluation.", + "hydra:supportedOperation": [ + { "hydra:method": "POST", "hydra:title": "recordPolicyDecision", "hydra:description": "Persists a PolicyDecision." } + ] + }, + { + "@id": "srcos:CapabilityToken", + "hydra:title": "CapabilityToken", + "hydra:description": "A short-lived, signed access grant derived from a PolicyDecision.", + "hydra:supportedOperation": [ + { "hydra:method": "POST", "hydra:title": "issueToken", "hydra:description": "Issues a CapabilityToken from a PolicyDecision." } + ] + }, + { + "@id": "srcos:WorkflowSpec", + "hydra:title": "WorkflowSpec", + "hydra:description": "A directed acyclic graph of WorkflowNodes with triggers and policy bindings.", + "hydra:supportedOperation": [ + { "hydra:method": "POST", "hydra:title": "upsertWorkflow", "hydra:description": "Creates or updates a WorkflowSpec." } + ] + }, + { + "@id": "srcos:RunRecord", + "hydra:title": "RunRecord", + "hydra:description": "The audit record of a single workload execution.", + "hydra:supportedOperation": [ + { "hydra:method": "POST", "hydra:title": "recordRun", "hydra:description": "Persists a RunRecord." } + ] + }, + { + "@id": "srcos:ProvenanceRecord", + "hydra:title": "ProvenanceRecord", + "hydra:description": "A W3C PROV-compatible lineage record for a RunRecord.", + "hydra:supportedOperation": [ + { "hydra:method": "POST", "hydra:title": "recordProvenance", "hydra:description": "Persists a ProvenanceRecord." } + ] + }, + { + "@id": "srcos:Comment", + "hydra:title": "Comment", + "hydra:description": "A free-text annotation on any addressable object.", + "hydra:supportedOperation": [ + { "hydra:method": "POST", "hydra:title": "createComment", "hydra:description": "Creates a Comment." } + ] + }, + { + "@id": "srcos:Rating", + "hydra:title": "Rating", + "hydra:description": "A 1–5 star rating on any addressable object.", + "hydra:supportedOperation": [ + { "hydra:method": "POST", "hydra:title": "createRating", "hydra:description": "Creates a Rating." } + ] + }, + { + "@id": "srcos:AgentSession", + "hydra:title": "AgentSession", + "hydra:description": "A single autonomous agent session.", + "hydra:supportedOperation": [ + { "hydra:method": "POST", "hydra:title": "upsertAgentSession", "hydra:description": "Creates or updates an AgentSession." } + ] + }, + { + "@id": "srcos:ExecutionDecision", + "hydra:title": "ExecutionDecision", + "hydra:description": "An immutable record of an agent's execution decision.", + "hydra:supportedOperation": [ + { "hydra:method": "POST", "hydra:title": "decideExecution", "hydra:description": "Records an ExecutionDecision." } + ] + }, + { + "@id": "srcos:SkillManifest", + "hydra:title": "SkillManifest", + "hydra:description": "A declared agent skill with activation rules and policy bindings.", + "hydra:supportedOperation": [ + { "hydra:method": "POST", "hydra:title": "upsertSkillManifest", "hydra:description": "Creates or updates a SkillManifest." } + ] + }, + { + "@id": "srcos:MemoryEntry", + "hydra:title": "MemoryEntry", + "hydra:description": "A persistent agent memory entry.", + "hydra:supportedOperation": [ + { "hydra:method": "POST", "hydra:title": "upsertMemoryEntry", "hydra:description": "Creates or updates a MemoryEntry." } + ] + }, + { + "@id": "srcos:SessionReceipt", + "hydra:title": "SessionReceipt", + "hydra:description": "The final outcome record for a completed AgentSession.", "hydra:supportedOperation": [ - { - "hydra:method": "POST", - "hydra:title": "evaluatePolicy" - } + { "hydra:method": "POST", "hydra:title": "recordSessionReceipt", "hydra:description": "Records a SessionReceipt." } ] } ] -} \ No newline at end of file +}