Skip to content

feat(registry): reproducible AgentKit foundation publishing and pinned whole-tree artifact API #54

Open

Description

@zuey-cloud-harness

Parent / cross-repo

Implementation slice of SkillX #34 and #21, tracked by SkillX #31; counterpart AgentKit #2274 and design prerequisite AgentKit #2275. Keep #34 as contract owner for generic registry, not a second registry implementation.

Objective

Create a first-class, trusted AgentKit publisher integration using SkillX's generic immutable whole-directory package/release model: export one self-contained AK foundation skill from the canonical AK repo and publish it manually and through scoped CI with exactly reproducible bytes; expose safe pinned artifact resolution for AgentKit consumers. Do not port AK's installer to TypeScript.

Start with real code

  • SkillX packages/contracts/src/package-manifest.ts, packages/skill-identity, apps/web/app/lib/db/registry-schema.ts, packages/cli/src/commands/publish.ts, apps/web/app/lib/security/content-scanner.ts, Github import/scan routes. Audit existing implementation vs phase-2 roadmap [Phase 2] Immutable registry and publishing CLI/CI #34.
  • AK kits/{core,engineer,marketing}/skills, kit.yaml, CLI package/release builder and exported resource closure.
  • Check exact upstream HEAD, doc ownership and current storage/migrations before designing migrations. Current skillx use emits SKILL.md text/metadata, not installable nested packages.

Scope / deliverables

  1. Define deterministic package closure: full recursive file manifest for SKILL.md, references/, scripts/, assets/, modules/, nested arbitrary regular files plus declared runtime/deps; reject symlink, special file, hardlink, traversal, archive bombs, unsafe modes, secrets and overlimit resources with stable errors. Explicit policy for tests/build artefacts/metadata.
  2. Reuse skillx.package/v1 package identity (@agentkit/ak-...), exact semver/release state. Separate source identity (Git repo+path+commit) from namespace ownership and immutable artifact digest. Release version cannot be overwritten with different bytes.
  3. Stable deterministic pack process (canonical relative paths, file ordering, timestamps, modes, UTF-8/machine-independent canonical manifest; no platform-dependent hash drift). Per-file SHA-256, archive SHA-256, SBOM/dependency metadata where applicable. Publish idempotently.
  4. Secure R2/artifact distribution through explicit versioned metadata + entitlement aware authorization + short-lived URL/stream and integrity checks; no link construction or redirects that bypass auth. Cache-policy and revocation/yank semantics documented for offline local digests.
  5. Publisher auth: scoped CI credential or OIDC trusted publish (where supported), namespace ownership, minimal permissions, no secrets in build output/README. Sign/attest artifact provenance if approved contract; do not block existing skill discovery unnecessarily.
  6. AK mapping: publish one small truly standalone foundation skill first, manually and through CI; reject bundles missing dependencies/hooks/sidecars rather than misrepresenting them as runnable. Curated kit export only after closure verified and SkillX [Phase 4] Hook packs and AgentKit reference publishing #36.
  7. Stable read-only inspect/resolve/download API contract supporting exact release+digest and compatibility metadata for Go consumer. Existing skillx use remains backwards compatible, labeled discovery-only when incomplete; no runtime execution during resolve.
  8. Security release lifecycle: draft/quarantine/review/publish/yank, publisher key rotation, replay controls and revoked/compromised source handling.

Required negative/repro tests

  • 94-file-style nested resources preserved; manifests/digests identical from clean builds; same version with changed bytes rejected; cross-runtime archive hash consistency.
  • Zip-slip / tar traversal, symlink pointing out, case/Unicode collision, Windows reserved paths, oversized/duplicate entries, malicious executable bit, leaked credential fixtures, malformed metadata, dependency closure missing.
  • Auth bypass on private/paid packages, forged namespace, CI publish token with overbroad permissions, partial upload, concurrent idempotent publish/retry, yanked/quarantined resolution.
  • Manual vs CI publishing of same snapshot yields identical digest; install/read path has no implicit code execution.

Agent implementation prompt

Implement a vertical slice within Phase 2 with its existing schema/migrations and tests, not a parallel marketplace. Read SkillX instructions, #21/#31/#34 and AK #2275 contract first. Produce an explicit contract+threat model and repo-file references. First implement deterministic full-tree pack+verify, then immutable upload/resolve/auth, finally a scoped AgentKit example publisher. Preserve existing routes/CLI use/search. Keep backward compatibility and feature flags for incomplete public APIs. Every failed verification must fail closed; never curl | sh. Open focused PR(s) with exact tests, artifact digests, no mutable latest refs, migration and rollback notes. Coordinate the API shape with the AgentKit SourceProvider issue before finalizing.

Non-goals

SkillX universal runtime installer, AK native installer rewrite, auto-activation of hooks/scripts, user personalization, paid creator settlement.

Acceptance

  • Generic [Phase 2] Immutable registry and publishing CLI/CI #34 contracts reused, no duplicate schema ownership.
  • Complete standalone skill published to SkillX manually + CI reproducibly.
  • Signed/attested publisher provenance decision documented and integrity verified.
  • Pinned, entitled artifact metadata+bytes resolvable by AK without executing.
  • Private/quarantined/yanked behavior and path/adversarial tests pass.
  • Cross-link implementation PR and AgentKit consumer issue.

Activity

  1. zuey-cloud-harness commented on Oct 11, 2026

    @zuey-cloud-harness
    Author

    Consumer/direct counterparts: AK #2277 (optional pinned SkillX read/cache/locked sync), AK #2275 (shared contracts), AK #2282 (full-tree/auth/reproducibility and no-exec E2E). Depends on generic immutable registry SX #34 and complete nested resources SX #21. AK Go installer remains separate.

  2. mrgoonie commented on Oct 11, 2026

    @mrgoonie
    Contributor

    AgentKit contract proposal for alignment: https://github.com/bestagentkits/agentkit/pull/2283 (docs/specs/skill-lifecycle-contract.md). Requests for this slice: (1) releaseDigest MUST equal the canonical tree digest agentkit.skill-tree/v1 of the release file tree (archive/artifact_digest = transport integrity only), so manual and CI releases hash identically regardless of container; (2) the SkillX publisher/verifier should pass the shared vectors docs/conformance/skill-lifecycle/skill-tree-v1-vectors.json (32 cases incl. traversal, NFC, case collision, reserved names, symlink, noise exclusion); (3) @agentkit/* is reserved for signed AgentKit kits. AgentKit owns the local lock; collection revisions resolve into it. Feedback welcome on the PR before it is accepted.

  3. mrgoonie commented on Oct 13, 2026

    @mrgoonie
    Contributor

    SX-3 merged in #59 (squash ec8e143). Evidence: CI green at head 2fc65bf; two isolated review rounds (round 2: 0 blockers, 0 majors); follow-ups in #61.

    Activation is NOT done:

    • SKILLX_RELEASES_API stays "0" in production; the release endpoint returns 404.
    • Before enabling it: back up D1, apply migration 0012_api_key_scopes remotely, then deploy.
    • Hosting: skillx-web runs on Workers Paid (10,000 subrequests per request), so the 5,000 per-release subrequest budget fits.
  4. mrgoonie commented on Oct 13, 2026

    @mrgoonie
    Contributor

    SX-4 merged in #64 (squash eb94997). It adds the pinned read API: release list, signed manifest by version or digest, file and artifact by digest with ?version=, and signing key IDs. Everything stays behind SKILLX_RELEASES_API (off).

    Evidence:

    Activation checklist (not done):

    • Back up D1, then apply 0012 remotely.
    • Deploy; this creates the RELEASE_READ_LIMITER binding, namespace 5401.
    • Optionally set SKILLX_REGISTRY_REVOKED_KEY_IDS as a secret.
    • Set SKILLX_RELEASES_API=1.

    Follow-ups:

    • The per-request D1 last_used_at write in API-key auth.
    • /files/* re-validates the manifest on every request.
    • Route-mount tests.
  5. mrgoonie commented on Oct 13, 2026

    @mrgoonie
    Contributor

    SX-5 landed in #66 (squash 6c5557a): release/publisher state API with audited compare-and-set (migration 0013, append-only triggers), admin containment of yanked releases in one batch, rate limiting before any write, 94-file nested full-tree E2E, runbook in docs/deployment-guide.md.

    Evidence: web typecheck 0; vitest 1180 pass, 1 known fail (#63); web build 0; local wrangler applied 0001-0013 and the triggers abort UPDATE/DELETE. Two independent review rounds, no open Blocker/High.

    Still owner steps (not done): back up D1, apply 0012 and 0013 remotely, then follow the runbook "Enable" section. Follow-ups tracked in the new limiter/real-D1 issue.

  6. zuey-cloud-harness commented on Oct 13, 2026

    @zuey-cloud-harness
    Author

    Progress snapshot 2026-10-14 00:25 ICT

    Source-code implementation slices SX-1..SX-5: 5/5 merged (100% of planned foundation registry slices), but production activation/issue acceptance NOT complete.

  7. mrgoonie commented on Oct 14, 2026

    @mrgoonie
    Contributor

    Release API activation (runbook in docs/deployment-guide.md), 2026-10-14:

    1. Backup: D1 Time Travel bookmark recorded before any change. A full d1 export is refused because the DB has FTS5 virtual tables, so the tables the migrations touch (api_keys, d1_migrations) were dumped separately, outside the repo.
    2. Migrations: 0012_api_key_scopes and 0013_release_state_audit applied remotely; both listed in d1_migrations; release_state_audit table plus release_state_audit_no_update / _no_delete triggers present.
    3. Flag-off deploy (after fix(releases): give state writes their own rate limiter #69, dedicated RELEASE_WRITE_LIMITER): both rate-limit bindings listed; GET /api/v1/packages/@agentkit/x/releases -> 404.
    4. Enable: feat(releases): enable the release API in production #70 merged and deployed (SKILLX_RELEASES_API = "1"). Live: unknown package -> 404 not_found, GET .../state -> 405, anonymous POST .../state -> 401 auth.required. Homepage 200.
    5. Supervised smoke: blocked by feat(registry): provision publishers so the enabled release API can publish #71. Production has no publisher rows and no provisioning path, so no scoped publish key or release can exist yet. 0 releases stored.

    Rollback stays: set the flag to "0" and redeploy.

  8. zuey-cloud-harness commented on Oct 14, 2026

    @zuey-cloud-harness
    Author

    Release API milestone update, 2026-10-14 10:59 ICT

    Important correction to 00:25 report: release API is now activated on production, but signed publish/consume acceptance remains BLOCKED.

  9. mrgoonie commented on Oct 14, 2026

    @mrgoonie
    Contributor

    Production activation smoke: passed (2026-10-14, runbook step 6)

    Throwaway release @skillx-smoke/activation-smoke@0.0.1 (channel beta) published with a releases:publish:@skillx-smoke scoped key.

    Step Result
    Publish 200, created: true, state: published, keyId skillx-reg-993cd14a011f7b76, findings []
    Replay same tree 200, created: false, same releaseDigest
    List 200, one release, newest first
    Manifest by version and by digest 200, byte-identical (805 B)
    File SKILL.md 200, sha256 matches the manifest entry
    Artifact 200, 2048 B, sha256 equals artifactDigest
    /api/v1/keys active [skillx-reg-993cd14a011f7b76], revoked []
    Independent verify AgentKit ak skills resolve/inspect/read (AGENTKIT_SKILLX=1, isolated home) verified the signature with its embedded production key and recomputed releaseDigest sha256:d345848f…1575
    Yank (owner account key) 200, published -> yanked
    Replay yank 409 state_conflict
    After yank list shows yanked; new resolution 410 release_yanked; locked read by digest 200
    Audit applied user published->yanked, stale user published->yanked, applied admin none->active (publisher)

    The smoke release stays yanked. The scoped key is to be revoked by the owner.

    Found on the way: #73 (built CLI bundle crashes on yaml dynamic require; smoke used a temporary createRequire shim) and #74 (Settings cannot create scoped keys; key created through the API).

  10. zuey-cloud-harness commented on Oct 14, 2026

    @zuey-cloud-harness
    Author

    Production publisher/smoke checkpoint, 2026-10-14 21:40 ICT

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions