Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions apps/web/app/lib/db/registry-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const publishers = sqliteTable(
handle: text("handle").notNull().unique(),
display_name: text("display_name").notNull(),
owner_user_id: text("owner_user_id"),
state: text("state").notNull().default("active"), // active | suspended | revoked
created_at: integer("created_at", { mode: "timestamp_ms" }).notNull(),
},
(table) => [index("idx_publishers_owner").on(table.owner_user_id)]
Expand All @@ -24,6 +25,7 @@ export const packages = sqliteTable(
name: text("name").notNull(), // fully-qualified '@handle/slug'
slug: text("slug").notNull(),
kind: text("kind").notNull(), // skill | hook-pack | bundle
visibility: text("visibility").notNull().default("public"), // public | private
created_at: integer("created_at", { mode: "timestamp_ms" }).notNull(),
updated_at: integer("updated_at", { mode: "timestamp_ms" }).notNull(),
},
Expand All @@ -48,15 +50,25 @@ export const packageReleases = sqliteTable(
artifact_key: text("artifact_key"), // R2 object key, populated by Phase 2
artifact_digest: text("artifact_digest"), // sha256:<64 hex>
artifact_size: integer("artifact_size"),
release_digest: text("release_digest"), // treeDigest of the file tree: sha256:<64 hex>
file_count: integer("file_count"),
tree_size: integer("tree_size"),
signed_manifest_key: text("signed_manifest_key"), // R2 key of the signed skillx.release/v1 manifest
source_provenance: text("source_provenance"), // JSON: repo, ref, commit
compatibility_json: text("compatibility_json"), // declared `compatible` map as JSON
created_at: integer("created_at", { mode: "timestamp_ms" }).notNull(),
published_at: integer("published_at", { mode: "timestamp_ms" }),
yanked_at: integer("yanked_at", { mode: "timestamp_ms" }),
quarantined_at: integer("quarantined_at", { mode: "timestamp_ms" }),
// Last signed skillx.release-status/v1 document: strictly increasing sequence and its issuedAt.
status_sequence: integer("status_sequence"),
status_issued_at: integer("status_issued_at", { mode: "timestamp_ms" }),
},
(table) => [
uniqueIndex("idx_package_releases_version").on(table.package_id, table.version),
index("idx_package_releases_state").on(table.release_state),
// Not unique: one tree may be released under several versions or packages.
index("idx_package_releases_digest").on(table.release_digest),
]
);

Expand Down
40 changes: 40 additions & 0 deletions apps/web/drizzle/migrations/0011_release_tree_digest.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
-- Release tree digest, signed manifest pointer, publisher state and package visibility (issue #54)
--
-- Strictly additive: nullable columns, or NOT NULL columns with a default, plus one index.
-- Existing rows keep every value; `publishers.state` becomes 'active' and
-- `packages.visibility` becomes 'public'. `release_digest` is the
-- agentkit.skill-tree/v1 tree digest named by the signed skillx.release/v1 manifest.
-- `status_sequence` and `status_issued_at` record the last signed skillx.release-status/v1
-- document, whose sequence must strictly increase.
--
-- NOTE ON DRIFT: `drizzle-kit generate` emitted CREATE TABLE for all seven registry tables
-- (publishers, packages, package_releases, release_verification_evidence, entitlements,
-- collections, collection_revisions), because the 0010 snapshot omits them although 0009
-- created them. Those statements were removed here; applying them would fail with "table
-- already exists". The 0011 snapshot records the full schema, which realigns the generator.
--
-- Rollback (SQLite/D1 support DROP COLUMN since 3.35; take a D1 time-travel bookmark first).
-- The last statement removes the wrangler bookkeeping row, so a later `migrations apply`
-- re-applies 0011 instead of skipping it:
-- DROP INDEX IF EXISTS idx_package_releases_digest;
-- ALTER TABLE package_releases DROP COLUMN status_issued_at;
-- ALTER TABLE package_releases DROP COLUMN status_sequence;
-- ALTER TABLE package_releases DROP COLUMN quarantined_at;
-- ALTER TABLE package_releases DROP COLUMN signed_manifest_key;
-- ALTER TABLE package_releases DROP COLUMN tree_size;
-- ALTER TABLE package_releases DROP COLUMN file_count;
-- ALTER TABLE package_releases DROP COLUMN release_digest;
-- ALTER TABLE packages DROP COLUMN visibility;
-- ALTER TABLE publishers DROP COLUMN state;
-- DELETE FROM d1_migrations WHERE name = '0011_release_tree_digest.sql';

ALTER TABLE `publishers` ADD `state` text DEFAULT 'active' NOT NULL;--> statement-breakpoint
ALTER TABLE `packages` ADD `visibility` text DEFAULT 'public' NOT NULL;--> statement-breakpoint
ALTER TABLE `package_releases` ADD `release_digest` text;--> statement-breakpoint
ALTER TABLE `package_releases` ADD `file_count` integer;--> statement-breakpoint
ALTER TABLE `package_releases` ADD `tree_size` integer;--> statement-breakpoint
ALTER TABLE `package_releases` ADD `signed_manifest_key` text;--> statement-breakpoint
ALTER TABLE `package_releases` ADD `quarantined_at` integer;--> statement-breakpoint
ALTER TABLE `package_releases` ADD `status_sequence` integer;--> statement-breakpoint
ALTER TABLE `package_releases` ADD `status_issued_at` integer;--> statement-breakpoint
CREATE INDEX `idx_package_releases_digest` ON `package_releases` (`release_digest`);
Loading
Loading