* feat(claws): publish hosted feed with OpenClaw proof * test(claws): prove package-local profile feed flow * fix(claws): encode scoped package artifact routes * fix(claws): enforce feed rollback and binding * test(claws): pin hosted OpenClaw contract proof * test(claws): add Convex feed runtime smoke * chore(schema): refresh experimental feed declarations --------- Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
8.2 KiB
summary, read_when
| summary | read_when | |||
|---|---|---|---|---|
| ClawHub publication contract for the stable OpenClaw hosted plugin, skill, and promotions feeds. |
|
Hosted Feeds
ClawHub is the canonical producer for the initial OpenClaw plugin and skill feeds and the runtime promotions feed. The feeds are projections of existing public package, release, skill, and promotion records; they are not second catalogs.
Contract
- Feed id:
clawhub-official - Schema version:
1 - Initial scope:
code-pluginandbundle-pluginpackages plus official skills - Source profiles:
public-clawhubfor ClawHub-hosted artifacts andpublic-githubfor source-backed skills available through the public feed - Entry identity: normalized ClawHub package name
- Install coordinate: package name plus exact release version
- Integrity:
sha256:<artifact sha256> - Publisher trust:
official, derived from ClawHub's official publisher state - Initial entry state:
available - Required feed metadata:
generatedAt, monotonicsequence, andexpiresAt
schemaVersion is a cross-repo wire contract with the OpenClaw hosted feed
consumer. Do not bump it until matching OpenClaw parser and validation support
has shipped, or current clients will reject the hosted feed and fall back to
bundled data.
Any pull request changing CATALOG_FEED_SCHEMA_VERSION must carry the
schema-version-approved label, added only after explicit approval confirms
that the matching OpenClaw parser and validation work is coordinated. A new
commit that changes the schema version automatically removes the label so the
current revision must be approved again.
The producer excludes soft-deleted packages, inactive releases, releases without an artifact digest, and releases blocked by ClawHub security or moderation state. The feed contains no registry URLs, credentials, source tokens, or bootstrap trust keys.
The feed intentionally emits RFC 19's canonical entry shape rather than
OpenClaw's current legacy bundled-catalog entries. The staged OpenClaw hosted
feeds stack must add its RFC-entry adapter before registry.openclaw.ai is
enabled as the default client feed; publishing this snapshot is otherwise
safe, but pre-adapter clients will fall back to their bundled catalog.
The skills feed uses the same envelope and /v1/feeds/skills route. It emits
type: "skill" entries with @<publisher>/<slug> ids and ClawHub install
coordinates. It includes only skills with an active latest published version,
non-empty files, a SHA-256 integrity hash, and an active official publisher
record. Both verified organization and personal publishers are included;
unverified publishers are excluded.
GitHub-backed skills are emitted only when the current upstream content is
available through the public feed gate: installKind: "github",
githubCurrentStatus: "present", githubScanStatus: "clean" or
"suspicious", no upstream removal marker, complete repo/path/commit/content
hash fields, and a live GitHub source row owned by the same official publisher.
These entries use a public-github candidate with the commit as version,
sha256:<githubCurrentContentHash> as integrity, and an additive github
object containing immutable repo, path, commit, and contentHash.
Suspicious GitHub-backed entries follow the same public feed visibility pattern
as suspicious hosted packages and skills.
Pending, failed, malicious, missing, removed, hidden, soft-deleted, or
incomplete GitHub-backed skills are not emitted.
Until the skills feed has pagination or sharding, it publishes at most 1000
eligible entries per snapshot so a large skills corpus does not block the plugin
feed publication path.
The experimental Claws feed is deliberately not an additive entry type in this stable v1 contract. Its separately gated parser, serializer, and route are specified in Experimental Claw Feed.
The promotions feed uses id clawhub-promotions, schema version 1, and the
/v1/feeds/promotions route. Entries are declarative promotion records, not
commands or executable content. They may identify providers, auth choices,
plugins, models, and HTTPS signup/docs/launch URLs. Only promotions with
status: "active" whose launch window has started are published. The active
set is capped at 50 records by the promotions write path, which also bounds each
snapshot. Public slug lookups keep ended promotions readable only when they
actually crossed their launch boundary; promotions canceled before launch stay
private permanently, even if their scheduled window or other fields are edited.
Expired drafts cannot be activated, and unlaunched active promotions cannot be
rescheduled wholly into an expired window. Model references and aliases are
single-line fields so management form serialization remains lossless.
The write path also enforces the OpenClaw consumer's authoring grammars so a
promotion can never publish in a shape clients reject or silently degrade on:
model refs, provider, and auth choice id are restricted to shell-safe
identifier characters because the CLI echoes them into copy-paste commands
and refuses anything else; aliases must be typed identifiers (letters,
digits, ._:-, no spaces) because the CLI skips aliases it cannot register;
plugin names use the package registry's canonical npm-safe grammar (scoped
@scope/name allowed); and when a provider is declared, every model ref must
start with <provider>/, matching the CLI's refusal to configure models
outside the promotion's declared provider.
Publication
convex/catalogFeed.ts builds the package, skill, and gated Claws feeds from
indexed package/skill queries and stores one current publication row per feed
in catalogFeedPublications.
Keeping one row per feed avoids an unbounded publication log while preserving
the sequence and exact payload needed for validators.
The Publish Hosted Catalog Feed workflow refreshes the snapshot every six
hours and can be run manually. It requires the existing Production environment
CONVEX_DEPLOY_KEY. The workflow currently publishes an unsigned feed; signed
envelopes require a separate production key-management decision and must not be
advertised to OpenClaw clients until the signing key and trust root are deployed.
convex/promotionsFeed.ts builds the promotions snapshot from the bounded active
set and stores it in the same publication table. Production backend deploys
publish an initial snapshot before contract verification. Promotion updates and
status changes schedule an immediate refresh. Active promotions also schedule
refreshes at startsAt and at endsAt + 1ms: both window endpoints are
inclusive, so the expiry refresh must run after the final active millisecond. A
six-hour cron is the backstop for long-running or empty feeds, keeping every
snapshot inside its 24-hour expiresAt horizon.
Edge delivery
The stable HTTP endpoints are /api/v1/feeds/plugins, /api/v1/feeds/skills,
and /api/v1/feeds/promotions. Each enabled endpoint
returns its stored bytes unchanged and provides:
ETag: "sha256:<payload hash>"Last-ModifiedCache-Control: public, max-age=60, s-maxage=300, stale-while-revalidate=86400Surrogate-Control: max-age=300, stale-while-revalidate=86400304 Not Modifiedfor matchingIf-None-MatchorIf-Modified-Since
Nitro exposes /v1/feeds/plugins, /v1/feeds/skills, and
/v1/feeds/promotions through the same environment-aware Convex proxy used for
/api/*. Their unversioned /feeds/* paths permanently redirect to the
versioned paths. The registry.openclaw.ai custom domain must point at the same
Vercel project before the public RFC URLs are enabled.
The serialized payload uses stable object-key ordering and deterministic entry and install-candidate ordering. Additive fields may be introduced within a major version; incompatible wire changes require a new versioned route and schema version.
/.well-known/openclaw-registry.json advertises the plugin and skill feeds.
/.well-known/clawhub.json remains the ClawHub API discovery document.
Do not make the feed request-time dynamic. Refresh the stored publication first, then let Vercel or the configured CDN cache the immutable response by ETag.