diff --git a/rfcs/0030-claw-composition-evidence.md b/rfcs/0030-claw-composition-evidence.md new file mode 100644 index 00000000..38fd9064 --- /dev/null +++ b/rfcs/0030-claw-composition-evidence.md @@ -0,0 +1,1302 @@ +--- +title: Claw Composition Evidence (Agent BOM) +authors: + - momothemage +created: 2026-08-05 +last_updated: 2026-08-05 +status: draft +issue: +rfc_pr: https://github.com/openclaw/rfcs/pull/60 +--- + +# Proposal: Claw Composition Evidence (Agent BOM) + +## Summary + +Define **Claw Composition Evidence**, presented to users as an **Agent Bill of +Materials (Agent BOM)**, as a bounded, immutable, registry-generated view of +the exact components and declarative resources contained in one exact Claw +release. Each composition snapshot is bound to the Claw artifact SHA-256 and +records the exact Skill and Plugin releases resolved at publication time. +ClawHub exposes current registry health separately so later moderation, +availability, and scan changes do not rewrite historical publication evidence. +The BOM helps users inspect a Claw before download while OpenClaw and other +applying clients remain authoritative for runtime mapping, local planning, +consent, mutation, provenance, update, and removal. + +## Status and related work + +This proposal extends, rather than replaces, the existing experimental Claws +contract: + +- [RFC 0016: Claws](https://github.com/openclaw/rfcs/pull/27) defines one Claw + as one complete new agent and assigns runtime planning and mutation to the + applying harness. +- [RFC 0016 profile addendum](https://github.com/openclaw/rfcs/pull/48) and + [RFC 0027: Claw application composition and clients](https://github.com/openclaw/rfcs/pull/52) + define portable package, harness-profile, native extension, bootstrap, and + client boundaries. They remain draft dependencies at the time of writing. +- [Claw project lifecycle](https://github.com/openclaw/rfcs/pull/56) and + [ClawHub exact-artifact publication](https://github.com/openclaw/clawhub/pull/3359) + are adjacent draft work. This proposal consumes an immutable stored artifact + identity but does not define how authors build that artifact. +- [Declared capability manifest issue](https://github.com/openclaw/clawhub/issues/2944) + is complementary. A BOM answers “what is included”; capability evidence + answers “what it declares or is observed to do.” + +The phrase **application composition** in RFC 0027 describes how a harness +realizes a complete Claw. **Composition evidence** in this RFC describes what +ClawHub can prove about one published package before application. These are +different owner surfaces. + +## Motivation + +ClawHub currently retains the exact Claw artifact and a bounded +ClawManifestSummary. The summary contains the agent identity and counts of +workspace files, Skills, Plugins, MCP servers, and cron jobs. It deliberately +does not expose the complete manifest, prompt body, or harness profile. + +That count-only summary is insufficient for the product promise in VISION.md +that users can inspect a Claw's publisher, components, permissions, and +security evidence: + +1. A count of three Skills does not say which Skills or exact releases are + included. +2. The manifest requires exact package versions, but ClawHub does not publish a + durable record of which registry releases and artifact digests those + coordinates resolved to. +3. Current scan or moderation status can change after publication. A mutable + graph alone cannot answer what was true when the Claw was published. +4. Parsing the Claw artifact on every detail-page read would repeat bounded + archive work, provide no indexed dependency identity, and still conflate + declaration with registry resolution. +5. OpenClaw can produce a rich local dry-run only after the artifact is + downloaded. ClawHub needs a safe pre-download evidence surface for + discovery, comparison, moderation impact, and feed consumers. + +The existing exact-version manifest and artifact SHA-256 provide the necessary +foundation. The missing layer is a safe, deterministic resolution record. + +## Terminology + +| Term | Meaning | +| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | +| Claw manifest | Author-declared portable fields and supported harness-profile declarations in the exact package artifact. | +| Subject | One exact Claw package name, version, and artifact SHA-256. | +| Component | An externally versioned installable artifact, initially a ClawHub Skill or Plugin and later a validated native extension coordinate. | +| Resource | A package-local or declarative effect such as a workspace destination, MCP server, cron job, bootstrap prompt, or harness profile. | +| Composition snapshot | Immutable safe projection generated from one exact subject and exact resolved component releases. | +| Composition digest | SHA-256 of the canonical snapshot content. | +| Current status | Mutable, read-time registry facts for the exact releases recorded in a snapshot. | +| Applying client | OpenClaw or another harness adapter that validates the artifact and plans local effects. | +| Agent BOM | User-facing product name for the snapshot plus its current status presentation. | + +This RFC does not claim SPDX or CycloneDX conformance. “BOM” describes the +product purpose, not a software-only SBOM interchange standard. + +## Goals + +- Let a user identify every direct externally versioned component in one exact + Claw release before downloading it. +- Bind the composition snapshot to the exact Claw artifact SHA-256. +- Resolve every portable ClawHub package coordinate to an exact release, + package family, artifact digest, publisher, and publication-time trust + evidence. +- Preserve publication-time evidence without hiding later moderation, + availability, or scan changes. +- Expose MCP, cron, workspace, bootstrap, and profile information through + explicitly safe projections. +- Keep list, search, and feed payloads small by carrying only a compact + composition reference outside the dedicated composition endpoint. +- Reuse existing package visibility, scanning, moderation, verification, and + download policy rather than inventing a second security policy. +- Keep OpenClaw authoritative for runtime compatibility, dry-run effects, + collisions, capabilities, consent, and local mutation. +- Support accessible grouped-list presentation and an optional graph from one + wire contract. +- Make the snapshot deterministic, bounded, versioned, testable, and suitable + for cross-repository conformance fixtures. + +## Non-Goals + +- Installing, updating, removing, or enabling any component. +- Replacing OpenClaw dry-run, plan-integrity consent, provenance, status, + doctor, or owner-specific cleanup. +- Claiming that a Claw or component is safe. +- Defining a new package manager, dependency solver, capability registry, or + runtime compatibility engine. +- Inferring undeclared transitive dependencies by scanning arbitrary source + code. +- Defining semantic deduplication between direct MCP declarations and + extension-owned MCP integrations. +- Publishing prompts, cron messages, workspace contents, profile source text, + secrets, resolved environment values, or full raw command lines. +- Making every package file a graph node. +- Supporting Claw-to-Claw dependencies in version 1. +- Requiring SPDX, CycloneDX, or another external BOM format in version 1. +- Graduating experimental Claws or removing their existing feature gates. +- Making the graph visualization the authoritative accessibility surface. + +## Proposal + +### Normative principles + +| Principle | Requirement | +| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | +| Exact subject | A snapshot describes exactly one Claw package version and artifact SHA-256. | +| Immutable history | Snapshot content is insert-only. Later registry changes never rewrite it. | +| Separate current truth | Availability, moderation, and scan changes are returned by a separate current-status projection. | +| Complete direct resolution | Every declared ClawHub Skill or Plugin coordinate is resolved or publication fails. No silent omission or truncation is allowed. | +| Existing policy ownership | “Installable” and “blocked” use existing package publication, visibility, moderation, scan, and download predicates. | +| Safe projection | Public snapshot fields are allowlisted. The full manifest and package-authored text are not copied into the snapshot. | +| Artifact authority | The exact artifact remains authoritative. A BOM is evidence about it, not a replacement package or installation plan. | +| Runtime authority | Applying clients revalidate the artifact and own runtime mapping, local conflicts, readiness, and consent. | +| No inherited trust | Root publisher trust does not propagate to component publishers. Every component shows its own evidence. | +| Bounded contract | Node counts, edge counts, string sizes, and serialized bytes have explicit shared limits. Oversized composition fails; it is never truncated. | +| Versioned behavior | Wire schema and generator contract versions are explicit. Old snapshots are not silently regenerated under new semantics. | + +### Owner boundary + +| Concern | ClawHub | Applying client | +| -------------------------------------------- | ------------------------------------- | --------------------------------- | +| Package identity and publisher | Authoritative | Consumes | +| Exact release and artifact resolution | Authoritative for ClawHub coordinates | Verifies downloaded bytes | +| Publish-time component evidence | Authoritative | May display or verify | +| Current registry moderation and availability | Authoritative | Enforces registry download result | +| Manifest and profile structure | Validates shared supported contract | Revalidates | +| Runtime extension mapping | Does not claim | Authoritative | +| Local filesystem, config, MCP, cron effects | Does not plan or mutate | Authoritative | +| Credentials and OAuth | Never stores or resolves | Canonical local owners | +| User consent | Does not replace | Authoritative | + +### Architecture + +```mermaid +flowchart LR + Author["Author artifact
CLAW.md + profiles + files"] --> Validate["ClawHub package validation"] + Validate --> Resolve["Exact component resolution"] + Resolve --> Snapshot["Immutable composition snapshot
bound to artifact SHA-256"] + Snapshot --> SnapshotAPI["Immutable composition API"] + Snapshot --> Detail["Claw detail / Agent BOM"] + Snapshot --> Feed["Compact feed reference"] + + Registry["Current package state
availability / moderation / scans"] --> Status["Live status projection"] + Status --> Detail + Status --> StatusAPI["Current-status API"] + + Feed --> Client["Applying client"] + SnapshotAPI --> Client + Client --> DryRun["Artifact verification + local dry-run"] + DryRun --> Consent["Explicit local consent"] + Consent --> Apply["Canonical owner mutations"] +``` + +**Figure 1.** ClawHub owns immutable registry evidence and current registry +facts. The applying client owns local behavior. + +### Three distinct records + +The implementation MUST preserve three distinct concepts: + +1. **Author declaration.** The exact manifest, prompt, profile, and package + files retained in the immutable artifact. +2. **Composition snapshot.** A safe immutable projection of the subject plus + exact registry resolutions observed during publication. +3. **Current status.** A mutable projection computed for the exact resolved + component releases when requested. + +The snapshot MUST NOT be updated when: + +- a component is later quarantined, revoked, or deleted; +- a publisher handle or verification tier changes; +- a newer component release is published; +- a later OpenClaw version maps a native extension differently; +- the Claw ceases to be the latest version. + +Those facts belong in current status or applying-client diagnostics. + +### Snapshot envelope and digest + +The public snapshot envelope has this conceptual shape: + +```json +{ + "schemaVersion": 1, + "digest": "sha256:0123...", + "recordedAt": "2026-08-05T10:00:00.000Z", + "origin": "publish", + "content": { + "generatorContract": "clawhub.claw-composition.v1", + "subject": {}, + "components": [], + "resources": [], + "edges": [], + "summary": {} + } +} +``` + +The digest is calculated only over the canonical UTF-8 serialization of +**content**. The digest MUST NOT include digest itself, recordedAt, storage +identifiers, internal database identifiers, request-specific URLs, or live +status. + +The schema-owned serializer MUST: + +- emit fields in a defined order; +- represent maps as arrays where ordering affects identity; +- sort components and resources by stable node id; +- sort edges by source id, relationship, then target id; +- sort set-like string arrays using Unicode code-point order; +- reject non-finite numbers and unknown fields; +- preserve validated string bytes rather than trimming into validity; +- emit no insignificant whitespace. + +This follows the repository's explicit deterministic feed serializer pattern +instead of relying on incidental object insertion order. + +The canonical digest format is lowercase **sha256:** followed by 64 hexadecimal +characters. + +### Digest taxonomy + +Composition integrity is a new identity and MUST NOT be confused with existing +artifact or applying-client identities: + +| Digest | Covers | Owner | Substitutable? | +| --------------------------------------- | -------------------------------------------------------------------------- | ---------------------------------- | ---------------------------------------------------------- | +| Claw artifact SHA-256 | Exact published archive bytes | ClawHub publication/artifact owner | No; this remains the download authority. | +| Composition digest | Canonical safe registry projection and exact resolved component identities | ClawHub composition owner | No; it does not authenticate omitted prompt or file bytes. | +| Applying-client package-snapshot digest | Applying client's canonical interpretation of extracted package inputs | Applying client | No; it may include harness-specific validated inputs. | +| Plan-integrity digest | Exact reviewed local effects and consent input | Applying client | No; it depends on local state and runtime mapping. | + +Consumers verify every digest required by their layer. Matching a composition +digest never permits skipping artifact verification, package validation, +dry-run, or plan-integrity consent. + +### Subject identity + +The subject contains: + +| Field | Requirement | +| ---------------- | ----------------------------------------------------------- | +| package | Canonical package name. | +| version | Exact release version. | +| family | Always claw for schema version 1. | +| artifact.kind | Stored artifact kind. | +| artifact.sha256 | Exact immutable artifact digest. Required. | +| publisher.handle | Publisher handle observed at snapshot time. | +| publisher.trust | Subject publisher trust evidence observed at snapshot time. | + +Internal Convex package, release, user, or publisher ids MUST NOT appear in the +public contract. + +### Stable node ids + +Node ids are deterministic within one snapshot and contain no database ids. +Recommended forms are: + +```text +root +package:skill:@acme/triage@1.2.0 +package:plugin:@acme/github@2.4.1 +profile:openclaw +mcp:github +cron:daily-triage +workspace:SOUL.md +bootstrap:BOOTSTRAP.md +``` + +All manifest-controlled id and path inputs are validated before node-id +construction. Duplicate node ids block snapshot generation. + +### Components + +Version 1 component nodes cover direct package dependencies. + +```json +{ + "id": "package:skill:@acme/triage@1.2.0", + "type": "package", + "declaredKind": "skill", + "resolvedFamily": "skill", + "name": "@acme/triage", + "version": "1.2.0", + "artifact": { + "kind": "npm-pack", + "sha256": "sha256:abcd..." + }, + "publisher": { + "handle": "acme", + "trust": "community" + }, + "evidenceAtResolution": { + "availability": "available", + "scanStatus": "clean", + "verification": { + "tier": "source-linked", + "scope": "artifact-only" + } + } +} +``` + +Required package fields are: + +- declared kind from the Claw manifest; +- exact canonical package name and version; +- resolved package family; +- exact component artifact SHA-256; +- publisher identity and trust evidence; +- publication-time availability and scan status; +- verification tier and scope when present; +- source/provenance summary when already safe and public in the package API. + +A declared Skill MUST resolve to family **skill**. A declared Plugin MUST +resolve to **code-plugin** or **bundle-plugin**. A Claw family release cannot be +referenced as a Skill or Plugin. + +The existing verification scope **dependency-graph-aware** MUST NOT be assigned +merely because a BOM exists. It may be used only when the verification process +actually validates the direct component graph and records evidence for that +claim. + +### Harness profiles and native extensions + +Composition generation MUST consume the profile inventory returned by the +shared Claw package validator. It MUST NOT implement independent profile +discovery rules that can drift from RFC 0016 or RFC 0027. + +Each validated profile is represented as a resource with: + +- harness namespace; +- validated package-relative path; +- profile schema version when known; +- safe operating-policy summary; +- declared native extension count; +- profile-present indicator. + +The raw profile body is not stored in the snapshot. + +Once an accepted shared profile schema exposes exact native extension +coordinates, those extensions may be emitted as component nodes. ClawHub may +record exact declaration and artifact identity, but it MUST NOT claim: + +- that the active OpenClaw version can map the bundle; +- that a foreign bundle format is usable; +- that required tools are ready; +- that local plugin setup or credentials are complete. + +Those are applying-client facts. Until the shared extension contract is +accepted, version 1 implementations emit the profile resource and bounded +counts only. + +### Resource projections + +Resources are declarative package effects, not independently installable +registry releases. + +#### Workspace resources + +Each declared destination may expose: + +- stable node id; +- destination path; +- category: bootstrap-file, managed-file, implicit-prompt, or application + content; +- source kind: package-file or claw-markdown-body; +- presence only for package-root native bootstrap. + +It MUST NOT expose: + +- file contents; +- prompt contents; +- source text; +- user-local output; +- resolved local paths. + +The subject artifact digest authenticates the complete package bytes. The +public BOM does not need per-file content digests. + +#### MCP resources + +Each MCP resource may expose: + +- manifest server id; +- transport; +- safely parsed exact package coordinate for a package-backed stdio command; +- remote URL origin only; +- auth mode; +- environment variable names, never values; +- tool-filter include and exclude names; +- timeout presence or bounded numeric values. + +It MUST NOT expose raw unresolved URL path, query, fragment, userinfo, arbitrary +command arguments, shell fragments, or resolved environment values. If a safe +package coordinate cannot be derived, the projection reports launch kind +**binary** or **unknown** without copying the command. + +#### Cron resources + +Each cron resource may expose: + +- job id and safe display name; +- cron expression; +- timezone; +- session mode; +- delivery mode and channel category. + +It MUST NOT expose the message body or a digest of the message body. Omitting a +digest avoids equality and dictionary attacks against short package-authored +instructions. + +#### Bootstrap resources + +A non-empty CLAW.md body is represented as an implicit managed SOUL.md +workspace resource with content redacted. Optional package-root BOOTSTRAP.md is +represented by presence, lifecycle category, and path only. + +The BOM MUST NOT publish either prompt. OpenClaw's existing redaction invariant +for preview, status, and automation output remains unchanged. + +#### Profile policy resources + +A profile safe summary may expose explicitly validated policy fields useful for +pre-download understanding, such as: + +- sandbox mode, scope, and workspace access; +- tool profile and allow/deny names; +- memory-search posture; +- heartbeat presence; +- native extension count. + +Unknown profile fields and full profile source remain excluded. The safe +projection changes only through a versioned composition schema or generator +contract update. + +### Edges + +Version 1 uses explicit, directed relationships: + +| Relationship | Source | Target | +| ------------------ | ------- | -------------------------- | +| includes | root | Skill or Plugin component | +| declares-profile | root | Harness profile | +| declares-extension | Profile | Native extension component | +| configures-mcp | root | MCP resource | +| schedules | root | Cron resource | +| writes-workspace | root | Workspace resource | +| seeds-bootstrap | root | Native bootstrap resource | + +Version 1 does not infer edges between external components. Because portable +package references cannot target Claws, the direct graph cannot contain a +Claw-to-Claw cycle. If Claw nesting is proposed later, cycle detection, maximum +depth, and maximum expanded-node rules require a new contract. + +```mermaid +graph TD + Root["Claw @acme/github-triage@1.0.0"] + Skill["Skill @acme/triage@1.2.0"] + Plugin["Plugin @acme/github@2.4.1"] + Profile["OpenClaw profile"] + MCP["MCP github"] + Cron["Cron daily-triage"] + Soul["Workspace SOUL.md
content redacted"] + Bootstrap["BOOTSTRAP.md
presence only"] + + Root -->|includes| Skill + Root -->|includes| Plugin + Root -->|declares-profile| Profile + Root -->|configures-mcp| MCP + Root -->|schedules| Cron + Root -->|writes-workspace| Soul + Root -->|seeds-bootstrap| Bootstrap +``` + +**Figure 2.** Version 1 is intentionally a direct composition graph. A grouped +list and this graph are two views of the same nodes and edges. + +### Summary + +The snapshot carries a derived summary: + +```json +{ + "componentCount": 2, + "skillCount": 1, + "pluginCount": 1, + "nativeExtensionCount": 0, + "profileCount": 1, + "mcpServerCount": 1, + "cronJobCount": 1, + "workspaceResourceCount": 2 +} +``` + +The existing ClawManifestSummary remains the list/search compatibility +projection. It is not replaced in the initial rollout. Detail responses may add +a compact composition reference containing schema version, digest, summary, +and URL. + +### Resolution rules + +Snapshot generation resolves only exact declared coordinates. + +For each package declaration, ClawHub MUST: + +1. canonicalize and look up the package using the existing registry owner; +2. find the exact requested release; +3. verify the declared kind against resolved package family; +4. require an immutable artifact SHA-256; +5. evaluate publication, deletion, visibility, moderation, scan, and download + policy through existing helpers; +6. capture safe publisher, artifact, verification, and source evidence; +7. create the component node and root edge. + +Resolution failure codes should be stable and machine-readable: + +| Code | Meaning | +| -------------------------------- | ---------------------------------------------------------------------------------- | +| composition_package_not_found | Canonical package does not exist or is not visible to the publish context. | +| composition_version_not_found | Exact version does not exist or is not visible. | +| composition_family_mismatch | Declared Skill/Plugin kind does not match package family. | +| composition_artifact_unavailable | Exact release lacks an immutable install artifact digest. | +| composition_dependency_blocked | Existing package security or moderation policy blocks the release. | +| composition_visibility_mismatch | A Claw would expose or require a dependency its intended consumers cannot resolve. | +| composition_limit_exceeded | Complete safe projection exceeds a contract limit. | +| composition_duplicate_node | Two declarations produce the same stable node id. | + +Errors MUST include the manifest declaration path and human-readable context, +but clients branch on the code rather than message text. + +Public Claws MUST NOT resolve to a dependency that an anonymous public consumer +cannot download. Private dependency behavior must reuse the existing +authenticated package-resolution contract; it must not be invented inside the +BOM endpoint. + +### Publication lifecycle and consistency + +Composition generation is part of staged Claw publication: + +```mermaid +sequenceDiagram + participant P as Publisher + participant H as ClawHub publication + participant R as Package registry + participant S as Security pipeline + participant D as Durable storage + + P->>H: Upload exact Claw artifact + expected SHA-256 + H->>H: Verify artifact and validate package + H->>R: Resolve exact declared package releases + R-->>H: Release ids and immutable artifact identities + H->>D: Stage pending release and exact resolution references + H->>S: Run existing publication checks + S-->>H: Publish or block decision + H->>R: Re-read exact releases and final evidence + alt all required dependencies remain installable + H->>H: Build final canonical safe snapshot + digest + H->>D: Atomically insert snapshot and publish release + else dependency changed or checks fail + H->>D: Keep release blocked with no public snapshot + end +``` + +**Figure 3.** Dependency installability is checked before staging and again +before final publication to close the publication-time race. + +The pre-publication stage stores exact resolution references, not a +publication-time snapshot. Finalization MUST use those same exact component +release ids, re-read their current evidence, and build the public immutable +snapshot inside the publish decision. It must not resolve a tag or select a +newer version. Snapshot insertion and release publication are one atomic +outcome, so no visible release can lack its required publish-origin snapshot +and no failed release can expose one. + +If a component becomes blocked after final publication, the subject snapshot +remains visible wherever historical version detail remains visible. Current +status reports the block and install-oriented feeds omit the Claw until all +required components are installable again. + +### Current status + +Current status is a separate response with separate cache semantics: + +```json +{ + "schemaVersion": 1, + "compositionDigest": "sha256:0123...", + "evaluatedAt": "2026-08-05T11:00:00.000Z", + "overall": "attention", + "components": [ + { + "id": "package:skill:@acme/triage@1.2.0", + "availability": "available", + "scanStatus": "pending", + "verificationTier": "source-linked" + } + ] +} +``` + +Overall states are deliberately not safety claims: + +| State | Meaning | +| --------- | ------------------------------------------------------------------------------------------------------------------------------------ | +| available | Every required exact component remains installable under current registry policy and no non-blocking attention signal is present. | +| attention | Components remain installable, but at least one current signal such as pending, suspicious, not-run, or stale evidence needs review. | +| blocked | At least one required exact component cannot currently be installed. | +| unknown | ClawHub could not complete a current evaluation. | + +The UI MUST say “available” or “no current blocking signal,” never “safe.” + +Current status may include: + +- exact-release availability; +- soft deletion or owner deletion; +- manual moderation state; +- effective scan status; +- verification tier and scope; +- trust-staleness indicators; +- publisher handle and trust changes when safely available. + +It MUST NOT claim runtime compatibility, credential readiness, MCP reachability, +extension mapping support, workspace collision safety, or successful local +installation. + +### HTTP API + +The proposed endpoints are: + +```text +GET /api/v1/packages/{name}/versions/{version}/composition +GET /api/v1/packages/{name}/versions/{version}/composition/status +``` + +The exact-version package route remains the authorization and visibility +boundary. Composition handlers first prove that the caller may view the +subject release, then return only fields permitted for that subject. + +#### Snapshot endpoint + +- Returns one exact immutable composition snapshot. +- Uses the composition digest as ETag. +- Uses no-store or mandatory revalidation while subject visibility and the + experimental gate can change. Immutable content does not imply immutable + authorization. +- Returns 404 when Claws are disabled, the subject is not a Claw, the release + is not visible, or no snapshot exists. +- Does not parse the artifact on each read. + +A future content-addressed public route may use immutable caching only after +maintainers explicitly decide that a once-public composition remains public +after subject moderation, deletion, or visibility changes. + +#### Status endpoint + +- Returns current registry facts for the exact component release references. +- Uses no-store or a short explicitly bounded cache. +- Never mutates the snapshot. +- Returns unknown rather than presenting stale partial evaluation as complete. + +#### Existing package detail + +Exact-version and latest-version detail may add: + +```json +{ + "composition": { + "schemaVersion": 1, + "digest": "sha256:0123...", + "summary": { + "componentCount": 2, + "mcpServerCount": 1, + "cronJobCount": 1 + }, + "url": "/api/v1/packages/%40acme%2Fgithub-triage/versions/1.0.0/composition" + } +} +``` + +List and search responses retain the existing count-only +ClawManifestSummary. They do not embed node arrays or live status. + +### Experimental feed + +The current experimental Claw feed is a strict schema-version-1 contract. It +must not receive unknown fields without a coordinated schema update. + +A later feed slice may introduce schema version 2 with: + +```json +{ + "composition": { + "schemaVersion": 1, + "digest": "sha256:0123...", + "url": "https://clawhub.ai/api/v1/packages/.../composition" + } +} +``` + +Feed entries continue to carry the exact Claw artifact integrity. Composition +integrity is additional evidence, not a substitute. Claws whose current status +is blocked are omitted from install-oriented feeds, preserving the existing +feed eligibility model. + +The ClawHub-to-OpenClaw bridge test must verify: + +1. strict feed parsing; +2. exact artifact bytes against feed integrity; +3. composition bytes against composition digest; +4. composition subject identity against feed package/version/artifact; +5. safe extraction; +6. real OpenClaw add dry-run; +7. absence of prompt, cron-message, and resolved-secret text in feed, + composition, and serialized plan output. + +OpenClaw local-file and development flows do not require a ClawHub BOM. + +### CLI + +The ClawHub CLI should extend package inspection rather than introduce a +second Claw lifecycle: + +```text +clawhub package inspect @acme/github-triage@1.0.0 --composition +clawhub package inspect @acme/github-triage@1.0.0 --composition --json +``` + +Human output groups: + +1. subject and publisher; +2. exact Skills and Plugins; +3. harness profiles and native-extension declarations; +4. MCP servers; +5. scheduled work; +6. workspace and bootstrap effects; +7. publication-time evidence; +8. current registry attention or blocking facts. + +The CLI MUST label publication-time and current facts separately. It MUST NOT +perform local installation or imply that registry availability guarantees a +successful OpenClaw plan. + +### Web experience + +The Claw version detail page adds a **Components** section or tab. + +The authoritative accessible view is a grouped table/list with: + +- exact component name and version; +- component publisher; +- artifact and provenance link; +- publication-time scan and verification evidence; +- current availability and attention state; +- MCP, cron, profile, bootstrap, and workspace safe summaries; +- a clear link to the exact Claw artifact. + +An optional graph uses the same nodes and edges. It is secondary presentation, +not the only way to access information. Keyboard, screen-reader, narrow-screen, +and no-JavaScript fallbacks use the grouped representation. + +The page visually separates: + +- **Published composition** — immutable historical snapshot; +- **Current registry status** — mutable facts evaluated now; +- **Local install effects** — unavailable until an applying-client dry-run. + +### Storage model + +Use a dedicated table rather than expanding packageReleases: + +```text +clawCompositionSnapshots + packageId + packageReleaseId + schemaVersion + generatorContract + subjectArtifactSha256 + compositionDigest + origin + recordedAt + content + internalResolutionRefs + +indexes + by_release_schema + by_digest +``` + +Reasons: + +- Convex reads whole documents. Generic list/detail queries should not pay for + the full graph. +- Snapshot immutability and schema evolution are clearer outside the mutable + package release document. +- Current-status evaluation needs internal release references that must not be + exposed publicly. + +The table validator MUST describe the complete safe shape; content MUST NOT use +an unbounded any validator. + +Insertion semantics: + +- one snapshot per package release and schema version; +- retry with the same digest is idempotent; +- retry with a different digest fails closed and requires investigation; +- no ordinary update mutation exists; +- internal resolution refs are storage metadata, not part of the public digest; +- pending publication stores resolution input, not a public snapshot; +- blocked or failed publication exposes no publish-origin snapshot. + +Current status is computed from internal exact-release references. Version 1 +does not require a second durable status table. A later cache must carry +evaluatedAt and must never be mistaken for snapshot content. + +### Bounds + +The initial proposed limits are: + +| Limit | Value | +| ---------------------------------- | ------------: | +| Direct portable package components | 128 | +| Native extension components | 128 | +| MCP server resources | 64 | +| Cron resources | 128 | +| Managed workspace resources | 512 | +| Harness profiles | 16 | +| Total nodes | 1,024 | +| Total edges | 2,048 | +| Canonical snapshot content | 512 KiB UTF-8 | + +Limits apply before storage and public serialization. Every emitted node and +edge counts. Unknown or unsupported resource kinds fail validation; they are +not silently dropped. + +These limits are composition limits, not permission to exceed existing tighter +archive, manifest, profile, managed-file, or applying-client limits. Before +implementation acceptance, ClawHub and OpenClaw must publish matching +conformance vectors for any limit that also constrains accepted packages. + +### Security and privacy invariants + +The snapshot is an allowlisted derivative, never a redacted copy of arbitrary +input. + +It MUST NOT contain: + +- CLAW.md Markdown body; +- SOUL.md, AGENTS.md, BOOTSTRAP.md, or other workspace contents; +- cron message bodies or hashes; +- environment values; +- URL query, fragment, or userinfo; +- raw arbitrary command arguments; +- resolved credentials, OAuth state, channel bindings, provider configuration, + or local paths; +- scanner raw evidence that is not already public under package security APIs; +- internal Convex ids; +- private dependency metadata visible beyond the subject's authorization. + +Additional requirements: + +- Publication validates and serializes through one shared schema. +- Unknown fields are rejected. +- Every public string and array has an explicit bound. +- Node ids cannot contain control characters or unsafe path forms. +- Public and private authorization tests cover subject and dependency + visibility. +- Composition generation performs no package script execution and no network + call to author-declared endpoints. +- Remote MCP origins are parsed using URL APIs and emitted only after removing + path, query, fragment, and credentials. +- Current status reuses canonical package-security policy. +- UI copy never turns a scan, Official publisher, or available state into a + safety guarantee. + +### Moderation impact + +A future internal query may use internal resolution refs to find Claws affected +by one exact component release. That enables: + +- moderator impact previews before quarantine or revocation; +- owner notifications; +- “affected Claws” diagnostics; +- security-advisory targeting. + +This reverse index is not required for the first public API slice. If added, it +must use indexed exact-release references and bounded pagination; it must not +scan all snapshots or all package releases. + +### Versioning + +Composition schema version and generator contract are separate: + +- **schemaVersion** controls the public wire shape and parser. +- **generatorContract** controls projection and resolution semantics within + that shape. + +Adding a new optional safe field may still require a generator-contract change +when it changes the digest. Changing node identity, edge semantics, required +fields, safe projection, or canonical serialization requires a new public +schema version. + +Existing immutable snapshots are never rewritten to a new generator contract. +A later schema may coexist for the same release under a separate +by-release-and-schema record. + +### Existing releases and reconstruction + +The implementation MUST NOT fabricate publication-time evidence for releases +published before this contract. + +Options for an existing experimental release are: + +1. no snapshot, with the UI saying composition evidence is unavailable; or +2. an explicit reconstructed snapshot generated from the immutable artifact + and exact registry state at reconstruction time. + +Reconstructed snapshots use origin **reconstructed** and recordedAt reflects +reconstruction time. UI and API must not label that evidence as observed at +original publication. + +Because Claws remain experimental, the recommended initial rollout is: + +- generate publish-origin snapshots for new releases; +- reconstruct only maintained fixture or official experimental releases needed + for conformance; +- do not run a broad production backfill until maintainers accept semantics and + operational cost. + +Any broad Convex backfill requires the repository's migration workflow, +cursor-based batches, progress and resume support, dry-run evidence, and real +Convex runtime validation. + +### Feature gating and rollout + +All public surfaces remain behind CLAWHUB_EXPERIMENTAL_CLAWS. A second +user-visible feature flag is not required. Internal rollout controls may stage +snapshot generation, API reads, UI, and feed consumption independently. + +Recommended stages: + +1. schema, canonical serializer, privacy fixtures, and contract documentation; +2. publication resolver and immutable snapshot storage; +3. exact-version composition and status APIs plus CLI inspection; +4. grouped web presentation and optional graph; +5. feed schema update and cross-repository consumer proof; +6. version diff, reverse impact, advisories, capability evidence, and external + BOM export. + +Removing the Claws gate requires a separate stable compatibility and migration +decision. This RFC does not make that decision. + +## Example + +For this manifest fragment: + +```yaml +packages: + - kind: skill + source: clawhub + ref: "@acme/triage" + version: 1.2.0 + - kind: plugin + source: clawhub + ref: "@acme/github" + version: 2.4.1 +mcpServers: + github: + transport: streamable-http + url: https://mcp.example.com/github?tenant=private + auth: oauth +cronJobs: + - id: daily-triage + schedule: + cron: "0 9 * * 1-5" + timezone: America/Los_Angeles + session: isolated + message: "Private package-authored instruction omitted from BOM" +``` + +The safe snapshot contains: + +```json +{ + "schemaVersion": 1, + "digest": "sha256:...", + "recordedAt": "2026-08-05T10:00:00.000Z", + "origin": "publish", + "content": { + "generatorContract": "clawhub.claw-composition.v1", + "subject": { + "package": "@acme/github-triage", + "version": "1.0.0", + "family": "claw", + "artifact": { + "kind": "npm-pack", + "sha256": "sha256:root..." + }, + "publisher": { + "handle": "acme", + "trust": "community" + } + }, + "components": [ + { + "id": "package:plugin:@acme/github@2.4.1", + "type": "package", + "declaredKind": "plugin", + "resolvedFamily": "code-plugin", + "name": "@acme/github", + "version": "2.4.1", + "artifact": { + "kind": "npm-pack", + "sha256": "sha256:plugin..." + }, + "publisher": { + "handle": "acme", + "trust": "community" + }, + "evidenceAtResolution": { + "availability": "available", + "scanStatus": "clean" + } + }, + { + "id": "package:skill:@acme/triage@1.2.0", + "type": "package", + "declaredKind": "skill", + "resolvedFamily": "skill", + "name": "@acme/triage", + "version": "1.2.0", + "artifact": { + "kind": "npm-pack", + "sha256": "sha256:skill..." + }, + "publisher": { + "handle": "acme", + "trust": "community" + }, + "evidenceAtResolution": { + "availability": "available", + "scanStatus": "clean" + } + } + ], + "resources": [ + { + "id": "mcp:github", + "type": "mcp-server", + "transport": "streamable-http", + "endpointOrigin": "https://mcp.example.com", + "auth": "oauth" + }, + { + "id": "cron:daily-triage", + "type": "cron-job", + "cron": "0 9 * * 1-5", + "timezone": "America/Los_Angeles", + "session": "isolated" + } + ], + "edges": [ + { + "from": "root", + "relationship": "includes", + "to": "package:plugin:@acme/github@2.4.1" + }, + { + "from": "root", + "relationship": "includes", + "to": "package:skill:@acme/triage@1.2.0" + }, + { + "from": "root", + "relationship": "configures-mcp", + "to": "mcp:github" + }, + { + "from": "root", + "relationship": "schedules", + "to": "cron:daily-triage" + } + ], + "summary": { + "componentCount": 2, + "skillCount": 1, + "pluginCount": 1, + "nativeExtensionCount": 0, + "profileCount": 0, + "mcpServerCount": 1, + "cronJobCount": 1, + "workspaceResourceCount": 0 + } + } +} +``` + +The URL query and cron message are absent even though they remain authenticated +by the root artifact digest. + +## Rationale + +### Why snapshot plus current status? + +Only a snapshot preserves what exact releases and evidence were observed at +publication. Only a live projection can warn that one of those releases later +became blocked. Combining them in one mutable record either destroys history or +serves stale safety information. + +### Why not expand ClawManifestSummary? + +ClawManifestSummary is deliberately small and appears on generic detail and +feed surfaces. Expanding it into a graph would inflate common reads, mix +immutable and mutable fields, complicate list caching, and duplicate internal +resolution references on the package release document. It remains the compact +compatibility summary. + +### Why not parse the artifact on every read? + +Repeated archive parsing spends work on an immutable input, cannot prove what +registry releases were resolved during publication, offers no indexed reverse +impact path, and increases the public request attack surface. Publication is +the correct bounded seam for validation and resolution. + +### Why not let OpenClaw compute the only BOM? + +OpenClaw is authoritative for local effects, but it runs after download and +depends on local state and runtime version. ClawHub owns discovery, package +identity, publisher evidence, exact release resolution, and current registry +moderation. A registry BOM and local install plan answer different questions. + +### Why not store only the full manifest? + +The full manifest contains package-authored text and fields that should not +become a broad public projection. It also lacks resolved release identity and +current registry evidence. The artifact already preserves the full manifest. +The snapshot is an allowlisted derivative, not a second source of truth. + +### Why not adopt SPDX or CycloneDX immediately? + +Those formats are valuable for software artifacts, but a Claw also contains +MCP declarations, schedules, workspace effects, prompts, and harness policy. +Forcing those into an external schema before the native contract stabilizes +would create lossy extensions and distract from the registry boundary. A later +export can map package component nodes into CycloneDX while preserving the +native composition schema. + +### Why a direct graph first? + +Current portable contracts declare direct exact Skill and Plugin references. +They do not provide one trustworthy transitive dependency graph across all +package families. A direct graph is complete for the declared contract and +avoids presenting scanner inference as package truth. + +### Alternatives considered + +| Alternative | Verdict | +| ----------------------------------------- | ------------------------------------------------------------------------------- | +| One mutable graph on packageReleases | Rejected: destroys historical evidence and inflates common documents. | +| Count-only summary plus artifact download | Rejected: users cannot inspect exact components before download. | +| Parse and resolve on demand | Rejected: repeated cost, weaker evidence, no durable resolution identity. | +| OpenClaw-only plan | Rejected: wrong owner for registry discovery and pre-download trust. | +| Full manifest public API | Rejected: privacy and ownership boundary violation. | +| Scanner-inferred dependency graph | Rejected for v1: observation is not declaration and may be incomplete. | +| Immediate universal SBOM format | Deferred: native resources do not map cleanly and the contract is experimental. | + +## Implementation plan + +The detailed repository and test plan lives in +[0030/implementation-plan.md](0030/implementation-plan.md). + +The intended PR sequence is: + +1. **PR 0 — RFC:** this document, diagrams, contract decisions, and sidecar + implementation plan. +2. **PR 1 — Schema and canonical serialization:** public types, validators, + limits, privacy fixtures, stable diagnostic codes, and deterministic digest. +3. **PR 2 — Resolution and immutable storage:** publication-time resolver, + staged/finalization checks, dedicated table, and current-status query owner. +4. **PR 3 — HTTP API and CLI:** exact-version composition/status endpoints, + compact detail reference, and package-inspect output. +5. **PR 4 — Web presentation:** grouped accessible BOM, current-status + separation, and optional direct graph. +6. **PR 5 — Feed and applying-client proof:** coordinated experimental feed + schema update and real OpenClaw dry-run bridge. +7. **PR 6 — Follow-ups:** version diff, reverse impact, advisories, capability + evidence, and external format export. + +Every implementation PR remains independently testable and behind the existing +experimental Claws gate. + +## Acceptance criteria + +1. Every newly published visible Claw release has one immutable composition + snapshot bound to its exact artifact SHA-256. +2. The same subject artifact, exact resolved release records, publication-time + evidence, and schema/generator contract produce the same canonical bytes and + digest. +3. Every declared ClawHub Skill and Plugin coordinate resolves to an exact + release or publication fails with a stable diagnostic. +4. Family mismatch, missing version, missing artifact digest, blocked release, + visibility mismatch, duplicate node, and limit overflow fail closed. +5. Publication finalization rechecks the same exact component releases and + cannot silently select newer versions. +6. Snapshot content never changes because of later moderation, scan, + publisher, latest-version, or runtime changes. +7. Current status reports later registry changes without mutating the + composition digest. +8. Public responses contain no prompt, workspace content, bootstrap content, + cron message, environment value, credential-bearing URL, raw arbitrary + command line, local path, or internal database id. +9. Public and private authorization tests prove that composition does not leak + subject or dependency metadata. +10. List and search responses remain compact and do not read full composition + documents. +11. Exact-version composition uses deterministic ETag behavior while + revalidating mutable authorization; current status has separate bounded + cache semantics. +12. UI and CLI visibly separate publication-time evidence, current registry + facts, and unavailable-until-dry-run local effects. +13. No UI label claims “safe” based on availability, scanning, Official + publisher, or verification alone. +14. Applying-client behavior remains unchanged: artifact verification, + runtime mapping, local planning, explicit consent, and canonical mutation + remain authoritative. +15. The cross-repository fixture verifies feed, artifact, composition, and real + OpenClaw dry-run identities without leaking package-authored prompt text. +16. Existing experimental releases are either explicitly unavailable or + labeled reconstructed; none are presented as publish-origin evidence. +17. Disabled Claw deployments fail closed for publication and all composition + read surfaces. +18. The accepted schema includes complete validators and shared conformance + vectors for limits, canonical ordering, redaction, and digest calculation. + +## Unresolved questions + +Maintainer decisions required before PR 1: + +1. Are the proposed node and byte limits appropriate, or should accepted RFC + 0016/OpenClaw source limits define lower shared values? +2. Should private Claws with private exact dependencies be supported in version + 1, or should version 1 require every dependency to be publicly resolvable? +3. Should a post-publication blocked dependency omit the Claw from the + install-oriented feed, as recommended here, or publish a blocked entry in a + newly versioned feed contract? +4. Should the first implementation reconstruct any current official + experimental releases, or require republish for publish-origin evidence? +5. Should profile-policy safe summaries land in PR 1, or follow only after RFC + 0016 addendum and RFC 0027 profile contracts are accepted? +6. Is **Claw Composition Evidence** the preferred normative name, with + **Agent BOM** reserved for product UI, or should both API and UI use one + name? + +Questions explicitly deferred beyond version 1: + +- transitive dependency declarations and Claw nesting; +- declared-versus-observed capability comparison; +- component advisory subscriptions and notifications; +- CycloneDX or SPDX export; +- multi-version composition diff; +- cross-registry component coordinates; +- runtime-specific readiness aggregation. diff --git a/rfcs/0030/implementation-plan.md b/rfcs/0030/implementation-plan.md new file mode 100644 index 00000000..d81945bb --- /dev/null +++ b/rfcs/0030/implementation-plan.md @@ -0,0 +1,423 @@ +# Claw Composition Evidence implementation plan + +This sidecar translates the Agent BOM RFC into bounded, dependency-aware pull +requests. It is implementation guidance, not a substitute for the normative +contract in [the RFC](../0030-claw-composition-evidence.md). + +## Dependency map + +```mermaid +flowchart TD + RFC["PR 0
RFC and decisions"] --> Schema["PR 1
Schema + canonical digest"] + Schema --> Backend["PR 2
Resolver + immutable storage"] + Backend --> API["PR 3
HTTP API + CLI"] + API --> UI["PR 4
Web BOM"] + API --> Feed["PR 5a
Claw feed v2"] + Feed --> Consumer["PR 5b
OpenClaw consumer proof"] + UI --> Follow["PR 6
Diff / impact / advisories"] + Consumer --> Follow + + Exact["Exact Claw artifact contract
ClawHub #3359 or equivalent"] --> Backend + Profiles["Accepted RFC 0016/0027 profile contract"] --> Schema +``` + +## PR 0: RFC + +### Scope + +- Agree on snapshot versus current-status separation. +- Agree on safe fields and forbidden fields. +- Agree on publication failure and recheck semantics. +- Agree on naming, limits, authorization, and reconstruction policy. +- Record non-overlap with RFC 0027 application composition. +- Record dependency on an immutable exact artifact identity. + +### Files + +- rfcs/0030-claw-composition-evidence.md +- rfcs/0030/implementation-plan.md + +### Validation + +- Markdown link and Mermaid rendering inspection. +- Cross-check against VISION.md, specs/claws.md, + specs/experimental-claw-feed.md, packages/schema/src/claws.ts, + packages/schema/src/clawPackage.ts, packages/schema/src/packages.ts, + convex/packages.ts, convex/schema.ts, and current OpenClaw RFC drafts. +- Verify no code, public API, or production behavior changes. + +### Exit gate + +Maintainers resolve or explicitly defer the six version-1 questions in the RFC. +Do not start public schema implementation while naming, visibility, safe +projection, or post-publication blocking semantics remain ambiguous. + +## PR 1: Schema and canonical serialization + +### Primary owner + +packages/schema + +### Proposed files + +- packages/schema/src/clawComposition.ts +- packages/schema/src/clawComposition.test.ts +- packages/schema/src/index.ts +- generated schema distribution files +- mirrored CLI schema only through the repository's normal generation path + +### Deliverables + +- Snapshot envelope and content validators. +- Component, resource, edge, summary, and current-status schemas. +- Explicit distinction between artifact, composition, applying-client package + snapshot, and plan-integrity digests. +- Stable node-id construction helpers. +- Stable diagnostic codes. +- Explicit serializer with deterministic field and collection ordering. +- SHA-256 digest helper over canonical content bytes. +- Contract limit constants. +- Safe-projection helpers for MCP URL origins, environment key names, cron, + workspace destinations, prompt presence, and profiles. +- Shared fixtures for valid and rejected snapshots. + +### Required tests + +- Same logical unordered input produces byte-identical canonical output. +- Every field change covered by identity changes the digest. +- recordedAt, storage ids, and current status do not change the digest. +- Unknown fields fail. +- Duplicate node ids and duplicate edges fail. +- Missing edge targets fail. +- Invalid digest format fails. +- Every limit has boundary-minus-one, boundary, and boundary-plus-one vectors. +- Unicode and portable path ordering are deterministic. +- URL userinfo, path, query, and fragment are absent. +- Prompt, cron message, environment value, and arbitrary command arguments + cannot be represented by the public schema. +- Parser round-trip preserves canonical content. + +### Exit gate + +- Schema TypeScript checks pass. +- Package schema test suite passes. +- Canonical fixture digest is committed as a cross-repository vector. +- A second independent implementation or small verification script reproduces + the fixture digest. + +## PR 2: Resolver and immutable storage + +### Primary owners + +- convex/packages.ts publication flow +- new convex/clawComposition.ts owner module +- convex/schema.ts + +Before writing Convex code, read convex/\_generated/ai/guidelines.md. + +### Proposed storage + +- clawCompositionSnapshots table. +- by_release_schema index. +- by_digest index. +- Internal release references stored separately from the public content shape. +- No generic list query reads snapshot documents. + +### Publication flow + +1. Verify and parse the exact Claw artifact. +2. Receive the validated Claw package result from the existing package + validator. +3. Resolve exact package coordinates through canonical package queries. +4. Validate family, version, artifact, visibility, and current installability. +5. Stage exact resolution references and validated safe resource input with the + pending package release. +6. Run existing publication security checks. +7. Re-read the exact recorded dependency releases during finalization. +8. Capture final publication-time evidence and build components, resources, + edges, and summary. +9. Canonicalize and hash. +10. Insert the snapshot and publish the release atomically, or block the + release without exposing a snapshot. + +### Idempotency + +- Same release/schema/digest retry returns the existing snapshot. +- Same release/schema with a different digest fails and records an operator- + visible error. +- No ordinary mutation updates snapshot content. + +### Current-status owner + +- Resolve internal exact release refs through indexed lookups or direct ids. +- Use existing package security, moderation, publication, deletion, and + download-policy helpers. +- Return unknown on incomplete evaluation. +- Do not perform runtime compatibility or network readiness checks. + +### Required tests + +- Valid Skill and both Plugin families resolve. +- Missing package/version and family mismatch fail with declaration paths. +- Missing artifact digest and blocked dependency fail. +- Public subject to private dependency fails. +- Subject authorization is checked before dependency metadata is returned. +- Dependency state changed before finalization blocks publication. +- Dependency state changed after publication leaves digest unchanged and + changes only current status. +- Retry idempotency and digest mismatch behavior. +- Pending publication has only internal resolution input; blocked publication + exposes no publish-origin snapshot. +- Existing generic package list/search paths do not read snapshots. +- Snapshot content remains below configured byte limit. +- Real Convex runtime validation covers indexes, validators, authorization, and + staged/final mutation behavior. + +### Exit gate + +- Focused package-publication and Convex runtime tests pass. +- Existing Claw publication E2E still passes. +- No new table scan or unindexed filter. +- Snapshot write and release finalization failure recovery are proven. + +## PR 3: HTTP API and CLI + +### Proposed API files + +- packages/schema/src/packages.ts +- packages/schema/src/routes.ts +- convex/httpApiV1/packagesV1.ts +- convex/httpApiV1.handlers.test.ts +- docs/http-api.md + +### Proposed CLI files + +- packages/clawhub/src/cli/commands/packages.ts +- packages/clawhub/src/cli/commands/packages.test.ts +- packages/clawhub/README.md or docs/cli.md + +### Deliverables + +- Exact-version composition snapshot endpoint. +- Exact-version current-status endpoint. +- Compact composition reference on exact/latest package detail. +- ETag plus no-store or mandatory revalidation for snapshot authorization. +- No-store or short-cache behavior for current status. +- Human and JSON package-inspect output. +- Feature-gate and family checks. + +### Required API tests + +- Public exact version success. +- Encoded scoped package name. +- Latest detail points to the exact latest release snapshot. +- Historical exact version points to its own snapshot. +- Non-Claw, disabled gate, missing snapshot, hidden release, private caller, and + blocked subject cases. +- Conditional ETag request. +- Current-status response changes without snapshot ETag change. +- Response-schema strictness. +- Prompt and sensitive-value absence over serialized bytes. + +### Required CLI tests + +- Grouped human output. +- JSON output exactly matches public schema. +- Publication-time versus current-state labels. +- Attention and blocked exit/output semantics. +- Missing composition evidence for pre-contract releases. +- No install or local mutation side effect. + +### Exit gate + +- HTTP E2E and CLI focused suites pass. +- Public docs state that BOM availability is not runtime readiness or safety. + +## PR 4: Web presentation + +### Scope + +- Exact-version Claw detail only. +- Grouped accessible list is required. +- Direct graph is optional and derives from the same response. +- Published composition and current registry status remain visually distinct. + +### Suggested components + +- ClawCompositionSummary +- ClawCompositionGroups +- ClawCompositionStatusBanner +- ClawCompositionGraph +- ClawCompositionEvidenceLegend + +Names are illustrative and should follow current route/component ownership. + +### User states + +- loading snapshot; +- snapshot available, status available; +- snapshot available, status attention; +- snapshot available, status blocked; +- snapshot available, status unknown; +- pre-contract release with no snapshot; +- Claws gate disabled; +- private or unauthorized; +- partial network failure where immutable snapshot loads but status does not. + +### Accessibility + +- Every graph fact appears in the grouped semantic list. +- Keyboard navigation does not require spatial graph interaction. +- Status is not color-only. +- Exact versions and publisher names are copyable text. +- Evidence timestamps use accessible absolute values with optional relative + display. +- Mobile layout does not require horizontal graph panning to reach facts. + +### Proof + +- Component and route tests. +- Real local ClawHub instance with seeded exact releases. +- Browser screenshots for available, attention, and blocked states. +- Keyboard/focus and narrow viewport checks. + +## PR 5a: Experimental feed contract + +### Dependency + +PR 3 API must be stable behind the experimental gate. + +### Scope + +- Bump the strict experimental Claw feed schema in coordination with its + consumer. +- Add composition schema version, digest, and URL. +- Keep exact artifact integrity as the install authority. +- Omit subjects with blocked current required dependencies. +- Preserve deterministic serialization. + +### Tests + +- Old and new parser compatibility decision is explicit. +- Unknown field behavior is intentional. +- Feed composition subject matches package/version/artifact. +- Blocked dependency removes entry. +- Feed serialization is deterministic. +- No full graph is embedded in feed. + +## PR 5b: Applying-client bridge + +### Scope + +- Consumer fetches or receives exact composition reference. +- Consumer verifies canonical bytes and digest. +- Consumer verifies subject coordinate and artifact digest match feed. +- Consumer downloads and verifies artifact independently. +- Real OpenClaw add dry-run remains the local authority. + +### Failure cases + +- Wrong composition digest. +- Composition subject/version mismatch. +- Composition artifact mismatch. +- Feed points to hidden or unauthorized composition. +- Component becomes blocked between feed generation and fetch. +- Composition endpoint unavailable. + +The accepted failure policy should fail closed for integrity mismatch and fall +back only where the experimental consumer contract explicitly allows a BOM- +unaware path. + +### Cross-repository evidence + +- Pin exact ClawHub and OpenClaw commits. +- Install frozen dependencies. +- Serve deterministic feed, composition, and artifact fixtures. +- Assert returned OpenClaw plan is non-mutating. +- Assert package-authored prompt and cron text do not occur in any serialized + registry or plan output. + +## PR 6: Follow-ups + +These are separate product decisions and should not inflate the MVP: + +### Version diff + +- Compare immutable snapshots by stable node id. +- Added, removed, version-changed, evidence-changed, and resource-policy- + changed groups. +- Do not compare live status as though it were package content. + +### Reverse impact + +- Normalize or index internal exact-release references for bounded reverse + lookup. +- Moderator preview and owner notification. +- Cursor pagination and no full-table scans. + +### Advisories + +- Attach one advisory to exact component release ids. +- Derive affected Claw releases from immutable references. +- Keep advisory claims separate from scanner verdicts. + +### Capability evidence + +- Link accepted declared capability evidence to component nodes. +- Compare declared versus observed only when scanner evidence has explicit + provenance and confidence. +- Never infer enforcement policy from the BOM alone. + +### External formats + +- Export package component subset to CycloneDX. +- Preserve MCP, cron, workspace, profile, and bootstrap resources through + documented extensions or a companion native document. +- Do not call the export complete if native resources are silently discarded. + +## Validation matrix + +| Invariant | Schema | Backend | API/CLI | UI | Cross-repo | +| ------------------------------ | -----------: | ------: | -------------: | -------------------: | --------------------: | +| Exact subject artifact binding | ✓ | ✓ | ✓ | display | ✓ | +| Deterministic digest | ✓ | ✓ | ✓ | display | ✓ | +| Exact dependency resolution | fixture | ✓ | display | display | ✓ | +| Snapshot immutability | fixture | ✓ | ETag | display | ✓ | +| Current status separation | schema | ✓ | ✓ | ✓ | ✓ | +| Prompt/secret redaction | ✓ | ✓ | byte assertion | rendering assertion | byte assertion | +| Authorization | schema shape | ✓ | ✓ | route state | authenticated fixture | +| Limits | ✓ | ✓ | response | large-state fallback | fixture | +| Gate disabled | parser | ✓ | ✓ | hidden/fail closed | ✓ | +| Runtime authority retained | N/A | N/A | copy | copy | real dry-run | + +## Estimated effort + +These are engineering estimates, not acceptance promises: + +| Slice | Estimate | +| -------------------- | --------------------------------------- | +| PR 0 RFC | 2–4 days including maintainer iteration | +| PR 1 schema | 4–6 days | +| PR 2 backend | 7–10 days | +| PR 3 API and CLI | 4–6 days | +| PR 4 web | 4–6 days | +| PR 5 feed and bridge | 5–8 days across repositories | + +The MVP is approximately 4–6 engineer-weeks for one contributor familiar with +the ClawHub publication and OpenClaw Claws contracts. Review latency and +cross-repository landing order are not included. + +## Landing order + +1. RFC acceptance. +2. Exact-artifact publication contract or equivalent immutable subject proof. +3. Shared schema and canonical digest. +4. Resolver and storage. +5. HTTP API and CLI. +6. Web grouped view. +7. Coordinated feed and applying-client bridge. +8. Optional graph polish and post-MVP work. + +No slice should advertise an installable BOM until its exact subject artifact, +complete direct resolution, safe projection, and digest verification are all +available.