@floomhq/skills 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2352,12 +2352,170 @@ var init_skill_package = __esm({
2352
2352
  }
2353
2353
  });
2354
2354
 
2355
- // ../shared/src/contract/index.ts
2355
+ // ../shared/src/contract/catalog-install.ts
2356
2356
  import { z as z2 } from "zod";
2357
- var CONTRACT_ERROR_CODES, ContractErrorCodeSchema, RequestIdSchema, IsoDateTimeSchema, IdSchema, SlugSchema, EmailSchema, Sha256Schema, VersionSeqSchema, UrlSchema, ErrorDetailSchema, ErrorEnvelopeSchema, UserSchema, WorkspaceSchema, MeResponseSchema, WorkspaceCreateRequestSchema, WorkspaceCreateResponseSchema, MemberSchema, MembersListResponseSchema, InviteStatusSchema, InviteCreateRequestSchema, InviteSchema, InviteCreateResponseSchema, InviteLinkRotateResponseSchema, InvitesListResponseSchema, InviteAcceptResponseSchema, TargetSchema, VersionRefSchema, PersonNameSchema, PersonNameEmailSchema, FileMetadataSchema, FileTreeEntrySchema, FileDownloadSchema, FileCopySchema, FileActionSchema, TextFileContentSchema, SafeExtractionSchema, BinaryMetadataSchema, NonTextFileContentSchema, FileContentSchema, SkillsListItemSchema, SkillsListResponseSchema, VersionHistoryItemSchema, SkillDetailResponseSchema, SkillVersionReadResponseSchema, ShareCreateRequestSchema, ShareCreateResponseSchema, PublicShareGetResponseSchema, DeviceSessionStateSchema, DeviceSessionResponseSchema, DeviceSessionActionResponseSchema, CliLibraryStateSchema, CliLibraryTargetQuerySchema, CliLibrarySkillSchema, CliLibraryResponseSchema, LocalManifestSkillSchema, LocalManifestSchema, ContractDecisionChecklistItemSchema, AGENT_TARGETS, AgentTargetSyncSchema, AgentMachineSchema, AgentsListResponseSchema, ActivityEventSchema, ActivityFeedResponseSchema, SkillSyncTargetEntrySchema, SkillSyncMachineSchema, SkillSyncStateResponseSchema;
2357
+ var UuidSchema, Sha256Schema, IsoDateTimeSchema, HexTokenSchema, Ed25519PublicKeySchema, Ed25519SignatureSchema, CATALOG_UPGRADE_FREEZES_AT, CatalogInstallAgentSchema, CatalogInstallMethodSchema, CatalogInstallOsSchema, CatalogInstallScopeSchema, CatalogInstallEnvironmentSchema, CatalogInstallerIdentitySchema, CatalogInstallerSupportCellSchema, CatalogInstallDurationBaselineSchema, CatalogUpgradeQualificationRuleSchema, CatalogInstallChallengeRequestSchema, CatalogInstallChallengeResponseSchema, CatalogInstallNonceRequestSchema, CatalogInstallNonceResponseSchema, CatalogInstallReceiptRequestSchema, CatalogUpgradeDispositionSchema, CatalogInstallReceiptResponseSchema;
2358
+ var init_catalog_install = __esm({
2359
+ "../shared/src/contract/catalog-install.ts"() {
2360
+ "use strict";
2361
+ UuidSchema = z2.string().uuid();
2362
+ Sha256Schema = z2.string().regex(/^[a-f0-9]{64}$/);
2363
+ IsoDateTimeSchema = z2.string().datetime({ offset: true });
2364
+ HexTokenSchema = z2.string().regex(/^[a-f0-9]{64}$/);
2365
+ Ed25519PublicKeySchema = z2.string().regex(/^[A-Za-z0-9+/]{43}=$/);
2366
+ Ed25519SignatureSchema = z2.string().regex(/^[A-Za-z0-9+/]{86}==$/);
2367
+ CATALOG_UPGRADE_FREEZES_AT = "2026-09-30T23:59:59.999999Z";
2368
+ CatalogInstallAgentSchema = z2.enum([
2369
+ "claude",
2370
+ "codex",
2371
+ "cursor",
2372
+ "gemini",
2373
+ "opencode"
2374
+ ]);
2375
+ CatalogInstallMethodSchema = z2.enum(["cli", "npx", "mcp"]);
2376
+ CatalogInstallOsSchema = z2.enum(["darwin", "linux", "windows"]);
2377
+ CatalogInstallScopeSchema = z2.enum(["global", "project"]);
2378
+ CatalogInstallEnvironmentSchema = z2.enum([
2379
+ "production",
2380
+ "preview",
2381
+ "staging",
2382
+ "ci",
2383
+ "platform_test",
2384
+ "floom_owned"
2385
+ ]);
2386
+ CatalogInstallerIdentitySchema = z2.object({
2387
+ name: z2.string().regex(/^[a-z0-9][a-z0-9._-]{0,63}$/),
2388
+ version: z2.string().regex(/^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?$/),
2389
+ artifact_sha256: Sha256Schema
2390
+ }).strict();
2391
+ CatalogInstallerSupportCellSchema = z2.object({
2392
+ installer: CatalogInstallerIdentitySchema,
2393
+ agent: CatalogInstallAgentSchema,
2394
+ target_os: CatalogInstallOsSchema,
2395
+ install_scope: CatalogInstallScopeSchema,
2396
+ install_method: CatalogInstallMethodSchema,
2397
+ support_status: z2.enum(["U", "S"]),
2398
+ valid_from: IsoDateTimeSchema,
2399
+ valid_until: IsoDateTimeSchema,
2400
+ evidence_manifest_sha256: Sha256Schema
2401
+ }).strict();
2402
+ CatalogInstallDurationBaselineSchema = z2.object({
2403
+ baseline_version: z2.string().regex(/^[a-z0-9][a-z0-9._-]{0,63}$/),
2404
+ cell: CatalogInstallerSupportCellSchema,
2405
+ sample_count: z2.number().int().min(100),
2406
+ p01_duration_ms: z2.number().int().positive(),
2407
+ corpus_sha256: Sha256Schema,
2408
+ evidence_manifest_sha256: Sha256Schema,
2409
+ excludes_warm_cache: z2.literal(true)
2410
+ }).strict();
2411
+ CatalogUpgradeQualificationRuleSchema = z2.object({
2412
+ version: z2.string().regex(/^[a-z0-9][a-z0-9._-]{0,63}$/),
2413
+ rule_hash: Sha256Schema,
2414
+ source_sha256: Sha256Schema,
2415
+ configuration_sha256: Sha256Schema,
2416
+ reconciliation_query_sha256: Sha256Schema,
2417
+ installer_registry_version: z2.string().min(1).max(64),
2418
+ goal_count: z2.literal(1e5),
2419
+ freezes_at: z2.literal(CATALOG_UPGRADE_FREEZES_AT)
2420
+ }).strict();
2421
+ CatalogInstallChallengeRequestSchema = z2.object({
2422
+ release_id: UuidSchema,
2423
+ agent: CatalogInstallAgentSchema,
2424
+ install_method: CatalogInstallMethodSchema,
2425
+ installer: CatalogInstallerIdentitySchema,
2426
+ target_os: CatalogInstallOsSchema,
2427
+ install_scope: CatalogInstallScopeSchema,
2428
+ environment: CatalogInstallEnvironmentSchema,
2429
+ installation_public_key: Ed25519PublicKeySchema,
2430
+ attribution_token: z2.string().min(32).max(256).nullable()
2431
+ }).strict();
2432
+ CatalogInstallChallengeResponseSchema = z2.object({
2433
+ challenge_id: UuidSchema,
2434
+ challenge_token: HexTokenSchema,
2435
+ proof_payload: z2.string().startsWith("floom-install-challenge-v2|"),
2436
+ server_manifest_sha256: Sha256Schema,
2437
+ expires_at: IsoDateTimeSchema
2438
+ }).strict();
2439
+ CatalogInstallNonceRequestSchema = z2.object({
2440
+ challenge_id: UuidSchema,
2441
+ challenge_token: HexTokenSchema,
2442
+ installer_attestation_signature: Ed25519SignatureSchema,
2443
+ installation_proof_signature: Ed25519SignatureSchema
2444
+ }).strict();
2445
+ CatalogInstallNonceResponseSchema = z2.object({
2446
+ nonce_id: UuidSchema,
2447
+ nonce_token: HexTokenSchema,
2448
+ installer_session_id: UuidSchema,
2449
+ installer_session_token: HexTokenSchema,
2450
+ release_id: UuidSchema,
2451
+ content_sha256: Sha256Schema,
2452
+ server_manifest_sha256: Sha256Schema,
2453
+ agent: CatalogInstallAgentSchema,
2454
+ install_method: CatalogInstallMethodSchema,
2455
+ installer: CatalogInstallerIdentitySchema,
2456
+ target_os: CatalogInstallOsSchema,
2457
+ install_scope: CatalogInstallScopeSchema,
2458
+ environment: CatalogInstallEnvironmentSchema,
2459
+ qualification_rule_id: UuidSchema,
2460
+ registry_version_id: UuidSchema,
2461
+ expires_at: IsoDateTimeSchema
2462
+ }).strict();
2463
+ CatalogInstallReceiptRequestSchema = z2.object({
2464
+ receipt_id: UuidSchema,
2465
+ nonce_id: UuidSchema,
2466
+ nonce_token: HexTokenSchema,
2467
+ installer_session_id: UuidSchema,
2468
+ installer_session_token: HexTokenSchema,
2469
+ release_id: UuidSchema,
2470
+ content_sha256: Sha256Schema,
2471
+ manifest_sha256: Sha256Schema,
2472
+ agent: CatalogInstallAgentSchema,
2473
+ install_method: CatalogInstallMethodSchema,
2474
+ installer: CatalogInstallerIdentitySchema,
2475
+ target_os: CatalogInstallOsSchema,
2476
+ install_scope: CatalogInstallScopeSchema,
2477
+ environment: CatalogInstallEnvironmentSchema,
2478
+ started_at: IsoDateTimeSchema,
2479
+ completed_at: IsoDateTimeSchema,
2480
+ result: z2.enum(["success", "failure"]),
2481
+ qualification_rule_id: UuidSchema,
2482
+ registry_version_id: UuidSchema,
2483
+ installation_public_key: Ed25519PublicKeySchema,
2484
+ installation_signature: Ed25519SignatureSchema
2485
+ }).strict().superRefine((receipt, context) => {
2486
+ if (Date.parse(receipt.completed_at) < Date.parse(receipt.started_at)) {
2487
+ context.addIssue({
2488
+ code: z2.ZodIssueCode.custom,
2489
+ path: ["completed_at"],
2490
+ message: "completed_at must not precede started_at"
2491
+ });
2492
+ }
2493
+ });
2494
+ CatalogUpgradeDispositionSchema = z2.enum([
2495
+ "qualified",
2496
+ "duplicate",
2497
+ "excluded",
2498
+ "quarantined",
2499
+ "released",
2500
+ "exclude_abuse",
2501
+ "continue_quarantine"
2502
+ ]);
2503
+ CatalogInstallReceiptResponseSchema = z2.object({
2504
+ receipt_id: UuidSchema,
2505
+ disposition: CatalogUpgradeDispositionSchema,
2506
+ reason_code: z2.string().min(1).max(120),
2507
+ rule_version: z2.string().min(1).max(64)
2508
+ }).strict();
2509
+ }
2510
+ });
2511
+
2512
+ // ../shared/src/contract/index.ts
2513
+ import { z as z3 } from "zod";
2514
+ var CONTRACT_ERROR_CODES, ContractErrorCodeSchema, RequestIdSchema, IsoDateTimeSchema2, IdSchema, SlugSchema, EmailSchema, Sha256Schema2, VersionSeqSchema, UrlSchema, ErrorDetailSchema, ErrorEnvelopeSchema, UserSchema, WorkspaceSchema, MeResponseSchema, WorkspaceCreateRequestSchema, WorkspaceCreateResponseSchema, MemberSchema, MembersListResponseSchema, InviteStatusSchema, InviteCreateRequestSchema, InviteSchema, InviteCreateResponseSchema, InviteLinkRotateResponseSchema, InvitesListResponseSchema, InviteAcceptResponseSchema, TargetSchema, VersionRefSchema, PersonNameSchema, PersonNameEmailSchema, FileMetadataSchema, FileTreeEntrySchema, FileDownloadSchema, FileCopySchema, FileActionSchema, TextFileContentSchema, SafeExtractionSchema, BinaryMetadataSchema, NonTextFileContentSchema, FileContentSchema, SkillsListItemSchema, SkillsListResponseSchema, VersionHistoryItemSchema, SkillDetailResponseSchema, SkillVersionReadResponseSchema, ShareCreateRequestSchema, ShareCreateResponseSchema, PublicShareGetResponseSchema, DeviceSessionStateSchema, DeviceSessionResponseSchema, DeviceSessionActionResponseSchema, CliLibraryStateSchema, CliLibraryTargetQuerySchema, CliLibrarySkillSchema, CliLibraryResponseSchema, LocalManifestSkillSchema, LocalManifestSchema, ContractDecisionChecklistItemSchema, AGENT_TARGETS, AgentTargetSyncSchema, AgentMachineSchema, AgentsListResponseSchema, ActivityEventSchema, ActivityFeedResponseSchema, SkillSyncTargetEntrySchema, SkillSyncMachineSchema, SkillSyncStateResponseSchema;
2358
2515
  var init_contract = __esm({
2359
2516
  "../shared/src/contract/index.ts"() {
2360
2517
  "use strict";
2518
+ init_catalog_install();
2361
2519
  CONTRACT_ERROR_CODES = [
2362
2520
  "UNAUTHENTICATED",
2363
2521
  "FORBIDDEN",
@@ -2365,6 +2523,7 @@ var init_contract = __esm({
2365
2523
  "VALIDATION_FAILED",
2366
2524
  "CONFLICT",
2367
2525
  "RATE_LIMITED",
2526
+ "SERVICE_UNAVAILABLE",
2368
2527
  "INTERNAL",
2369
2528
  "WORKSPACE_REQUIRED",
2370
2529
  "WORKSPACE_ALREADY_EXISTS",
@@ -2382,270 +2541,270 @@ var init_contract = __esm({
2382
2541
  "UNSAFE_FILE_PATH",
2383
2542
  "SKILL_MARKDOWN_REQUIRED"
2384
2543
  ];
2385
- ContractErrorCodeSchema = z2.enum(CONTRACT_ERROR_CODES);
2386
- RequestIdSchema = z2.string().min(1);
2387
- IsoDateTimeSchema = z2.string().datetime({ offset: true });
2388
- IdSchema = z2.string().uuid();
2389
- SlugSchema = z2.string().min(1).max(80).regex(/^(?=.{1,80}$)[a-z0-9]+(?:-[a-z0-9]+)*$/);
2390
- EmailSchema = z2.string().email().max(320);
2391
- Sha256Schema = z2.string().regex(/^[a-f0-9]{64}$/);
2392
- VersionSeqSchema = z2.number().int().positive();
2393
- UrlSchema = z2.string().url();
2394
- ErrorDetailSchema = z2.object({
2544
+ ContractErrorCodeSchema = z3.enum(CONTRACT_ERROR_CODES);
2545
+ RequestIdSchema = z3.string().min(1);
2546
+ IsoDateTimeSchema2 = z3.string().datetime({ offset: true });
2547
+ IdSchema = z3.string().uuid();
2548
+ SlugSchema = z3.string().min(1).max(80).regex(/^(?=.{1,80}$)[a-z0-9]+(?:-[a-z0-9]+)*$/);
2549
+ EmailSchema = z3.string().email().max(320);
2550
+ Sha256Schema2 = z3.string().regex(/^[a-f0-9]{64}$/);
2551
+ VersionSeqSchema = z3.number().int().positive();
2552
+ UrlSchema = z3.string().url();
2553
+ ErrorDetailSchema = z3.object({
2395
2554
  code: ContractErrorCodeSchema,
2396
- message: z2.string().min(1),
2555
+ message: z3.string().min(1),
2397
2556
  request_id: RequestIdSchema
2398
- }).catchall(z2.unknown());
2399
- ErrorEnvelopeSchema = z2.object({
2557
+ }).catchall(z3.unknown());
2558
+ ErrorEnvelopeSchema = z3.object({
2400
2559
  error: ErrorDetailSchema
2401
2560
  }).strict();
2402
- UserSchema = z2.object({
2561
+ UserSchema = z3.object({
2403
2562
  id: IdSchema,
2404
2563
  email: EmailSchema,
2405
- name: z2.string().min(1),
2564
+ name: z3.string().min(1),
2406
2565
  avatar_url: UrlSchema.nullable()
2407
2566
  }).strict();
2408
- WorkspaceSchema = z2.object({
2567
+ WorkspaceSchema = z3.object({
2409
2568
  id: IdSchema,
2410
2569
  slug: SlugSchema,
2411
- name: z2.string().min(1).max(120)
2570
+ name: z3.string().min(1).max(120)
2412
2571
  }).strict();
2413
- MeResponseSchema = z2.object({
2572
+ MeResponseSchema = z3.object({
2414
2573
  user: UserSchema,
2415
2574
  workspace: WorkspaceSchema.nullable()
2416
2575
  }).strict();
2417
- WorkspaceCreateRequestSchema = z2.object({
2418
- name: z2.string().trim().min(1).max(120)
2576
+ WorkspaceCreateRequestSchema = z3.object({
2577
+ name: z3.string().trim().min(1).max(120)
2419
2578
  }).strict();
2420
- WorkspaceCreateResponseSchema = z2.object({
2579
+ WorkspaceCreateResponseSchema = z3.object({
2421
2580
  workspace: WorkspaceSchema
2422
2581
  }).strict();
2423
- MemberSchema = z2.object({
2424
- name: z2.string().min(1),
2582
+ MemberSchema = z3.object({
2583
+ name: z3.string().min(1),
2425
2584
  email: EmailSchema,
2426
- joined_at: IsoDateTimeSchema
2585
+ joined_at: IsoDateTimeSchema2
2427
2586
  }).strict();
2428
- MembersListResponseSchema = z2.object({
2587
+ MembersListResponseSchema = z3.object({
2429
2588
  workspace: WorkspaceSchema,
2430
- members: z2.array(MemberSchema),
2431
- total: z2.number().int().nonnegative()
2589
+ members: z3.array(MemberSchema),
2590
+ total: z3.number().int().nonnegative()
2432
2591
  }).strict();
2433
- InviteStatusSchema = z2.enum([
2592
+ InviteStatusSchema = z3.enum([
2434
2593
  "pending",
2435
2594
  "accepted",
2436
2595
  "revoked",
2437
2596
  "expired"
2438
2597
  ]);
2439
- InviteCreateRequestSchema = z2.object({
2598
+ InviteCreateRequestSchema = z3.object({
2440
2599
  email: EmailSchema
2441
2600
  }).strict();
2442
- InviteSchema = z2.object({
2601
+ InviteSchema = z3.object({
2443
2602
  email: EmailSchema,
2444
2603
  status: InviteStatusSchema,
2445
- expires_at: IsoDateTimeSchema,
2446
- created_at: IsoDateTimeSchema
2604
+ expires_at: IsoDateTimeSchema2,
2605
+ created_at: IsoDateTimeSchema2
2447
2606
  }).strict();
2448
- InviteCreateResponseSchema = z2.object({
2607
+ InviteCreateResponseSchema = z3.object({
2449
2608
  invite: InviteSchema,
2450
2609
  accept_url: UrlSchema
2451
2610
  }).strict();
2452
- InviteLinkRotateResponseSchema = z2.object({
2611
+ InviteLinkRotateResponseSchema = z3.object({
2453
2612
  invite: InviteSchema,
2454
2613
  accept_url: UrlSchema
2455
2614
  }).strict();
2456
- InvitesListResponseSchema = z2.object({
2457
- invites: z2.array(InviteSchema),
2458
- total: z2.number().int().nonnegative()
2615
+ InvitesListResponseSchema = z3.object({
2616
+ invites: z3.array(InviteSchema),
2617
+ total: z3.number().int().nonnegative()
2459
2618
  }).strict();
2460
- InviteAcceptResponseSchema = z2.object({
2619
+ InviteAcceptResponseSchema = z3.object({
2461
2620
  invite: InviteSchema.extend({
2462
- status: z2.literal("accepted"),
2463
- accepted_at: IsoDateTimeSchema
2621
+ status: z3.literal("accepted"),
2622
+ accepted_at: IsoDateTimeSchema2
2464
2623
  }),
2465
2624
  workspace: WorkspaceSchema
2466
2625
  }).strict();
2467
- TargetSchema = z2.enum([
2626
+ TargetSchema = z3.enum([
2468
2627
  "claude",
2469
2628
  "codex",
2470
2629
  "cursor",
2471
2630
  "gemini",
2472
2631
  "opencode"
2473
2632
  ]);
2474
- VersionRefSchema = z2.object({
2633
+ VersionRefSchema = z3.object({
2475
2634
  version_seq: VersionSeqSchema,
2476
- display: z2.string().regex(/^v[1-9][0-9]*$/)
2635
+ display: z3.string().regex(/^v[1-9][0-9]*$/)
2477
2636
  }).strict().superRefine((value, context) => {
2478
2637
  if (value.display !== `v${value.version_seq}`) {
2479
2638
  context.addIssue({
2480
- code: z2.ZodIssueCode.custom,
2639
+ code: z3.ZodIssueCode.custom,
2481
2640
  message: "display must equal v${version_seq}",
2482
2641
  path: ["display"]
2483
2642
  });
2484
2643
  }
2485
2644
  });
2486
- PersonNameSchema = z2.object({
2487
- name: z2.string().min(1)
2645
+ PersonNameSchema = z3.object({
2646
+ name: z3.string().min(1)
2488
2647
  }).strict();
2489
2648
  PersonNameEmailSchema = PersonNameSchema.extend({
2490
2649
  email: EmailSchema
2491
2650
  }).strict();
2492
- FileMetadataSchema = z2.object({
2493
- path: z2.string().min(1).max(512),
2494
- size_bytes: z2.number().int().nonnegative(),
2495
- size: z2.number().int().nonnegative(),
2496
- sha256: Sha256Schema,
2497
- mime: z2.string().min(1)
2651
+ FileMetadataSchema = z3.object({
2652
+ path: z3.string().min(1).max(512),
2653
+ size_bytes: z3.number().int().nonnegative(),
2654
+ size: z3.number().int().nonnegative(),
2655
+ sha256: Sha256Schema2,
2656
+ mime: z3.string().min(1)
2498
2657
  }).strict();
2499
- FileTreeEntrySchema = z2.object({
2500
- path: z2.string().min(1).max(512),
2501
- kind: z2.enum(["directory", "file"]),
2502
- parent_path: z2.string().max(512).nullable(),
2503
- depth: z2.number().int().nonnegative(),
2504
- size_bytes: z2.number().int().nonnegative().nullable()
2658
+ FileTreeEntrySchema = z3.object({
2659
+ path: z3.string().min(1).max(512),
2660
+ kind: z3.enum(["directory", "file"]),
2661
+ parent_path: z3.string().max(512).nullable(),
2662
+ depth: z3.number().int().nonnegative(),
2663
+ size_bytes: z3.number().int().nonnegative().nullable()
2505
2664
  }).strict();
2506
- FileDownloadSchema = z2.object({
2507
- available: z2.boolean(),
2665
+ FileDownloadSchema = z3.object({
2666
+ available: z3.boolean(),
2508
2667
  url: UrlSchema.nullable(),
2509
- filename: z2.string().min(1).nullable(),
2510
- expires_at: IsoDateTimeSchema.nullable()
2668
+ filename: z3.string().min(1).nullable(),
2669
+ expires_at: IsoDateTimeSchema2.nullable()
2511
2670
  }).strict();
2512
- FileCopySchema = z2.object({
2513
- available: z2.boolean(),
2514
- source: z2.enum(["content_text", "safe_extraction", "none"])
2671
+ FileCopySchema = z3.object({
2672
+ available: z3.boolean(),
2673
+ source: z3.enum(["content_text", "safe_extraction", "none"])
2515
2674
  }).strict();
2516
- FileActionSchema = z2.object({
2675
+ FileActionSchema = z3.object({
2517
2676
  copy: FileCopySchema,
2518
2677
  download: FileDownloadSchema
2519
2678
  }).strict();
2520
2679
  TextFileContentSchema = FileMetadataSchema.extend({
2521
- mode: z2.literal("text"),
2522
- content_text: z2.string(),
2523
- safe_extraction: z2.null(),
2524
- binary: z2.null(),
2680
+ mode: z3.literal("text"),
2681
+ content_text: z3.string(),
2682
+ safe_extraction: z3.null(),
2683
+ binary: z3.null(),
2525
2684
  actions: FileActionSchema
2526
2685
  }).strict();
2527
- SafeExtractionSchema = z2.object({
2528
- status: z2.enum(["available", "truncated", "unsupported"]),
2529
- text_preview: z2.string().nullable(),
2530
- reason: z2.string().min(1).nullable()
2686
+ SafeExtractionSchema = z3.object({
2687
+ status: z3.enum(["available", "truncated", "unsupported"]),
2688
+ text_preview: z3.string().nullable(),
2689
+ reason: z3.string().min(1).nullable()
2531
2690
  }).strict();
2532
- BinaryMetadataSchema = z2.object({
2533
- filename: z2.string().min(1),
2534
- size_bytes: z2.number().int().nonnegative(),
2535
- sha256: Sha256Schema,
2536
- mime: z2.string().min(1),
2691
+ BinaryMetadataSchema = z3.object({
2692
+ filename: z3.string().min(1),
2693
+ size_bytes: z3.number().int().nonnegative(),
2694
+ sha256: Sha256Schema2,
2695
+ mime: z3.string().min(1),
2537
2696
  download_url: UrlSchema.nullable()
2538
2697
  }).strict();
2539
2698
  NonTextFileContentSchema = FileMetadataSchema.extend({
2540
- mode: z2.literal("non_text"),
2541
- content_text: z2.null(),
2699
+ mode: z3.literal("non_text"),
2700
+ content_text: z3.null(),
2542
2701
  safe_extraction: SafeExtractionSchema,
2543
2702
  binary: BinaryMetadataSchema,
2544
2703
  actions: FileActionSchema
2545
2704
  }).strict();
2546
- FileContentSchema = z2.discriminatedUnion("mode", [
2705
+ FileContentSchema = z3.discriminatedUnion("mode", [
2547
2706
  TextFileContentSchema,
2548
2707
  NonTextFileContentSchema
2549
2708
  ]);
2550
- SkillsListItemSchema = z2.object({
2709
+ SkillsListItemSchema = z3.object({
2551
2710
  slug: SlugSchema,
2552
- title: z2.string().min(1),
2553
- description: z2.string(),
2554
- icon: z2.string().min(1).nullable().optional(),
2711
+ title: z3.string().min(1),
2712
+ description: z3.string(),
2713
+ icon: z3.string().min(1).nullable().optional(),
2555
2714
  latest_version: VersionRefSchema,
2556
- updated_at: IsoDateTimeSchema,
2715
+ updated_at: IsoDateTimeSchema2,
2557
2716
  updated_by: PersonNameSchema
2558
2717
  }).strict();
2559
- SkillsListResponseSchema = z2.object({
2560
- skills: z2.array(SkillsListItemSchema),
2561
- total: z2.number().int().nonnegative(),
2562
- order: z2.literal("updated_desc"),
2563
- search: z2.object({
2564
- mode: z2.literal("client_side_only"),
2565
- server_search: z2.literal(false),
2566
- query_param: z2.null()
2718
+ SkillsListResponseSchema = z3.object({
2719
+ skills: z3.array(SkillsListItemSchema),
2720
+ total: z3.number().int().nonnegative(),
2721
+ order: z3.literal("updated_desc"),
2722
+ search: z3.object({
2723
+ mode: z3.literal("client_side_only"),
2724
+ server_search: z3.literal(false),
2725
+ query_param: z3.null()
2567
2726
  }).strict(),
2568
- pagination: z2.null()
2727
+ pagination: z3.null()
2569
2728
  }).strict();
2570
- VersionHistoryItemSchema = z2.object({
2729
+ VersionHistoryItemSchema = z3.object({
2571
2730
  version_seq: VersionSeqSchema,
2572
- display: z2.string().regex(/^v[1-9][0-9]*$/),
2573
- created_at: IsoDateTimeSchema,
2731
+ display: z3.string().regex(/^v[1-9][0-9]*$/),
2732
+ created_at: IsoDateTimeSchema2,
2574
2733
  created_by: PersonNameSchema,
2575
- changelog: z2.string().nullable().optional()
2734
+ changelog: z3.string().nullable().optional()
2576
2735
  }).strict().superRefine((value, context) => {
2577
2736
  if (value.display !== `v${value.version_seq}`) {
2578
2737
  context.addIssue({
2579
- code: z2.ZodIssueCode.custom,
2738
+ code: z3.ZodIssueCode.custom,
2580
2739
  message: "display must equal v${version_seq}",
2581
2740
  path: ["display"]
2582
2741
  });
2583
2742
  }
2584
2743
  });
2585
- SkillDetailResponseSchema = z2.object({
2586
- skill: z2.object({
2744
+ SkillDetailResponseSchema = z3.object({
2745
+ skill: z3.object({
2587
2746
  slug: SlugSchema,
2588
- title: z2.string().min(1),
2589
- description: z2.string(),
2747
+ title: z3.string().min(1),
2748
+ description: z3.string(),
2590
2749
  owner: PersonNameEmailSchema,
2591
- created_at: IsoDateTimeSchema,
2592
- license: z2.string().nullable().optional(),
2593
- min_floom: z2.string().nullable().optional(),
2750
+ created_at: IsoDateTimeSchema2,
2751
+ license: z3.string().nullable().optional(),
2752
+ min_floom: z3.string().nullable().optional(),
2594
2753
  latest: VersionRefSchema,
2595
- works_with: z2.array(TargetSchema),
2596
- files: z2.array(FileMetadataSchema),
2597
- versions: z2.array(VersionHistoryItemSchema)
2754
+ works_with: z3.array(TargetSchema),
2755
+ files: z3.array(FileMetadataSchema),
2756
+ versions: z3.array(VersionHistoryItemSchema)
2598
2757
  }).strict()
2599
2758
  }).strict();
2600
- SkillVersionReadResponseSchema = z2.object({
2601
- skill: z2.object({
2759
+ SkillVersionReadResponseSchema = z3.object({
2760
+ skill: z3.object({
2602
2761
  slug: SlugSchema,
2603
- title: z2.string().min(1),
2604
- description: z2.string()
2762
+ title: z3.string().min(1),
2763
+ description: z3.string()
2605
2764
  }).strict(),
2606
2765
  version: VersionHistoryItemSchema,
2607
- files: z2.array(FileMetadataSchema),
2608
- tree: z2.array(FileTreeEntrySchema),
2766
+ files: z3.array(FileMetadataSchema),
2767
+ tree: z3.array(FileTreeEntrySchema),
2609
2768
  selected_file: FileContentSchema.nullable(),
2610
- file_contents: z2.array(FileContentSchema)
2769
+ file_contents: z3.array(FileContentSchema)
2611
2770
  }).strict();
2612
- ShareCreateRequestSchema = z2.object({}).strict();
2613
- ShareCreateResponseSchema = z2.object({
2771
+ ShareCreateRequestSchema = z3.object({}).strict();
2772
+ ShareCreateResponseSchema = z3.object({
2614
2773
  url: UrlSchema,
2615
- token: z2.string().min(32)
2774
+ token: z3.string().min(32)
2616
2775
  }).strict();
2617
- PublicShareGetResponseSchema = z2.object({
2618
- skill: z2.object({
2619
- title: z2.string().min(1),
2620
- description: z2.string(),
2776
+ PublicShareGetResponseSchema = z3.object({
2777
+ skill: z3.object({
2778
+ title: z3.string().min(1),
2779
+ description: z3.string(),
2621
2780
  owner: PersonNameSchema,
2622
2781
  version: VersionRefSchema
2623
2782
  }).strict(),
2624
- files: z2.array(FileMetadataSchema),
2625
- tree: z2.array(FileTreeEntrySchema),
2783
+ files: z3.array(FileMetadataSchema),
2784
+ tree: z3.array(FileTreeEntrySchema),
2626
2785
  selected_file: FileContentSchema.nullable(),
2627
- file_contents: z2.array(FileContentSchema),
2628
- license: z2.string().nullable().optional()
2786
+ file_contents: z3.array(FileContentSchema),
2787
+ license: z3.string().nullable().optional()
2629
2788
  }).strict();
2630
- DeviceSessionStateSchema = z2.enum([
2789
+ DeviceSessionStateSchema = z3.enum([
2631
2790
  "pending",
2632
2791
  "approved",
2633
2792
  "denied",
2634
2793
  "expired"
2635
2794
  ]);
2636
- DeviceSessionResponseSchema = z2.object({
2795
+ DeviceSessionResponseSchema = z3.object({
2637
2796
  state: DeviceSessionStateSchema,
2638
- device: z2.object({
2639
- label: z2.string().min(1),
2640
- location: z2.string().min(1).nullable().optional(),
2641
- client: z2.string().min(1),
2642
- first_seen: IsoDateTimeSchema
2797
+ device: z3.object({
2798
+ label: z3.string().min(1),
2799
+ location: z3.string().min(1).nullable().optional(),
2800
+ client: z3.string().min(1),
2801
+ first_seen: IsoDateTimeSchema2
2643
2802
  }).strict()
2644
2803
  }).strict();
2645
- DeviceSessionActionResponseSchema = z2.object({
2804
+ DeviceSessionActionResponseSchema = z3.object({
2646
2805
  state: DeviceSessionStateSchema
2647
2806
  }).strict();
2648
- CliLibraryStateSchema = z2.enum([
2807
+ CliLibraryStateSchema = z3.enum([
2649
2808
  "active",
2650
2809
  "stale",
2651
2810
  "missing",
@@ -2653,90 +2812,1015 @@ var init_contract = __esm({
2653
2812
  "conflict",
2654
2813
  "unsupported_target"
2655
2814
  ]);
2656
- CliLibraryTargetQuerySchema = z2.object({
2815
+ CliLibraryTargetQuerySchema = z3.object({
2657
2816
  target: TargetSchema
2658
2817
  }).strict();
2659
- CliLibrarySkillSchema = z2.object({
2818
+ CliLibrarySkillSchema = z3.object({
2660
2819
  slug: SlugSchema,
2661
- title: z2.string().min(1),
2662
- description: z2.string(),
2820
+ title: z3.string().min(1),
2821
+ description: z3.string(),
2663
2822
  version: VersionRefSchema,
2664
- hash: Sha256Schema,
2823
+ hash: Sha256Schema2,
2665
2824
  state: CliLibraryStateSchema,
2666
- files: z2.array(FileContentSchema)
2825
+ files: z3.array(FileContentSchema)
2667
2826
  }).strict();
2668
- CliLibraryResponseSchema = z2.object({
2827
+ CliLibraryResponseSchema = z3.object({
2669
2828
  workspace: WorkspaceSchema,
2670
2829
  target: TargetSchema,
2671
- generated_at: IsoDateTimeSchema,
2672
- manifest_schema_version: z2.literal(1),
2673
- hash_basis: z2.literal("workspace_slug:skill_slug:version_seq:file_sha256"),
2674
- full_hash: Sha256Schema,
2675
- states: z2.array(CliLibraryStateSchema),
2676
- skills: z2.array(CliLibrarySkillSchema)
2830
+ generated_at: IsoDateTimeSchema2,
2831
+ manifest_schema_version: z3.literal(1),
2832
+ hash_basis: z3.literal("workspace_slug:skill_slug:version_seq:file_sha256"),
2833
+ full_hash: Sha256Schema2,
2834
+ states: z3.array(CliLibraryStateSchema),
2835
+ skills: z3.array(CliLibrarySkillSchema)
2677
2836
  }).strict();
2678
- LocalManifestSkillSchema = z2.object({
2837
+ LocalManifestSkillSchema = z3.object({
2679
2838
  slug: SlugSchema,
2680
2839
  version_seq: VersionSeqSchema,
2681
- hash: Sha256Schema,
2840
+ hash: Sha256Schema2,
2682
2841
  state: CliLibraryStateSchema,
2683
- installed_paths: z2.array(z2.string().min(1))
2842
+ installed_paths: z3.array(z3.string().min(1))
2684
2843
  }).strict();
2685
- LocalManifestSchema = z2.object({
2686
- manifest_schema_version: z2.literal(1),
2844
+ LocalManifestSchema = z3.object({
2845
+ manifest_schema_version: z3.literal(1),
2687
2846
  target: TargetSchema,
2688
2847
  workspace_slug: SlugSchema,
2689
- full_hash: Sha256Schema,
2690
- hash_basis: z2.literal("workspace_slug:skill_slug:version_seq:file_sha256"),
2691
- installed_at: IsoDateTimeSchema,
2692
- backup_path: z2.string().min(1).nullable(),
2693
- skills: z2.array(LocalManifestSkillSchema)
2848
+ full_hash: Sha256Schema2,
2849
+ hash_basis: z3.literal("workspace_slug:skill_slug:version_seq:file_sha256"),
2850
+ installed_at: IsoDateTimeSchema2,
2851
+ backup_path: z3.string().min(1).nullable(),
2852
+ skills: z3.array(LocalManifestSkillSchema)
2694
2853
  }).strict();
2695
- ContractDecisionChecklistItemSchema = z2.object({
2696
- id: z2.string().min(1),
2697
- title: z2.string().min(1),
2698
- locked: z2.literal(true)
2854
+ ContractDecisionChecklistItemSchema = z3.object({
2855
+ id: z3.string().min(1),
2856
+ title: z3.string().min(1),
2857
+ locked: z3.literal(true)
2699
2858
  }).strict();
2700
2859
  AGENT_TARGETS = ["claude", "codex", "cursor", "gemini", "opencode"];
2701
- AgentTargetSyncSchema = z2.object({
2702
- last_pulled_at: IsoDateTimeSchema.nullable()
2860
+ AgentTargetSyncSchema = z3.object({
2861
+ last_pulled_at: IsoDateTimeSchema2.nullable()
2703
2862
  }).strict();
2704
- AgentMachineSchema = z2.object({
2705
- machine_id: z2.string().uuid(),
2706
- machine_label: z2.string().min(1),
2707
- last_seen_at: IsoDateTimeSchema,
2708
- target_sync: z2.record(z2.enum(AGENT_TARGETS), AgentTargetSyncSchema)
2863
+ AgentMachineSchema = z3.object({
2864
+ machine_id: z3.string().uuid(),
2865
+ machine_label: z3.string().min(1),
2866
+ last_seen_at: IsoDateTimeSchema2,
2867
+ target_sync: z3.record(z3.enum(AGENT_TARGETS), AgentTargetSyncSchema)
2709
2868
  }).strict();
2710
- AgentsListResponseSchema = z2.object({
2711
- machines: z2.array(AgentMachineSchema),
2712
- total: z2.number().int().nonnegative()
2869
+ AgentsListResponseSchema = z3.object({
2870
+ machines: z3.array(AgentMachineSchema),
2871
+ total: z3.number().int().nonnegative()
2713
2872
  }).strict();
2714
- ActivityEventSchema = z2.object({
2873
+ ActivityEventSchema = z3.object({
2715
2874
  id: IdSchema,
2716
- event_name: z2.enum(["signup", "workspace_create", "push", "pull", "share_create", "skill_delete"]),
2717
- source: z2.enum(["web", "cli", "api"]),
2718
- target: z2.enum(AGENT_TARGETS).nullable(),
2719
- skill_slug: z2.string().nullable(),
2720
- created_at: IsoDateTimeSchema
2875
+ event_name: z3.enum(["signup", "workspace_create", "push", "pull", "share_create", "skill_delete"]),
2876
+ source: z3.enum(["web", "cli", "api"]),
2877
+ target: z3.enum(AGENT_TARGETS).nullable(),
2878
+ skill_slug: z3.string().nullable(),
2879
+ created_at: IsoDateTimeSchema2
2721
2880
  }).strict();
2722
- ActivityFeedResponseSchema = z2.object({
2723
- events: z2.array(ActivityEventSchema),
2724
- total: z2.number().int().nonnegative()
2881
+ ActivityFeedResponseSchema = z3.object({
2882
+ events: z3.array(ActivityEventSchema),
2883
+ total: z3.number().int().nonnegative()
2725
2884
  }).strict();
2726
- SkillSyncTargetEntrySchema = z2.object({
2885
+ SkillSyncTargetEntrySchema = z3.object({
2727
2886
  target: TargetSchema,
2728
- last_pulled_at: IsoDateTimeSchema
2887
+ last_pulled_at: IsoDateTimeSchema2
2729
2888
  }).strict();
2730
- SkillSyncMachineSchema = z2.object({
2889
+ SkillSyncMachineSchema = z3.object({
2731
2890
  machine_id: IdSchema,
2732
- machine_label: z2.string().min(1),
2733
- targets: z2.array(SkillSyncTargetEntrySchema)
2891
+ machine_label: z3.string().min(1),
2892
+ targets: z3.array(SkillSyncTargetEntrySchema)
2893
+ }).strict();
2894
+ SkillSyncStateResponseSchema = z3.object({
2895
+ machines: z3.array(SkillSyncMachineSchema),
2896
+ total_machines: z3.number().int().nonnegative(),
2897
+ total_targets_synced: z3.number().int().nonnegative()
2898
+ }).strict();
2899
+ }
2900
+ });
2901
+
2902
+ // ../shared/src/catalog.ts
2903
+ import { z as z4 } from "zod";
2904
+ var CatalogSlugSchema, CatalogPublicationStateSchema, CatalogProfileTypeSchema, CatalogSourceSchema, CatalogSourceRevisionSchema, CatalogProfileSchema, CatalogPersonSchema, CatalogCompanySchema, CatalogSkillSchema, CatalogReleaseSchema, CatalogStackSchema, CatalogStackVersionSchema, CatalogTaxonomyAxisSchema, CatalogAssignmentSourceSchema, CatalogEvidenceClassSchema, CatalogSkillLabelSchema, CatalogCompatibilitySchema, CatalogPermissionSchema, CatalogEvidenceEventSchema, CatalogRightsEventSchema, CatalogTrustAssertionSchema, CatalogTrustAssertionEventSchema;
2905
+ var init_catalog = __esm({
2906
+ "../shared/src/catalog.ts"() {
2907
+ "use strict";
2908
+ init_contract();
2909
+ CatalogSlugSchema = SlugSchema.refine((slug) => slug.length >= 3, {
2910
+ message: "catalog slugs must contain at least three characters"
2911
+ });
2912
+ CatalogPublicationStateSchema = z4.enum([
2913
+ "draft",
2914
+ "review",
2915
+ "published",
2916
+ "withdrawn"
2917
+ ]);
2918
+ CatalogProfileTypeSchema = z4.enum(["person", "company"]);
2919
+ CatalogSourceSchema = z4.object({
2920
+ id: IdSchema,
2921
+ source_type: z4.enum(["repository", "registry", "url", "manual"]),
2922
+ canonical_url: UrlSchema.nullable(),
2923
+ external_key: z4.string().trim().min(1).max(500).nullable(),
2924
+ display_name: z4.string().trim().min(1).max(200),
2925
+ license_expression: z4.string().trim().min(1).max(500).nullable(),
2926
+ source_state: z4.enum(["active", "withdrawn", "unavailable"]),
2927
+ observed_at: IsoDateTimeSchema2
2928
+ }).strict().superRefine((source, context) => {
2929
+ if (source.canonical_url === null && source.external_key === null) {
2930
+ context.addIssue({
2931
+ code: z4.ZodIssueCode.custom,
2932
+ path: ["canonical_url"],
2933
+ message: "a canonical URL or external key is required"
2934
+ });
2935
+ }
2936
+ });
2937
+ CatalogSourceRevisionSchema = z4.object({
2938
+ id: IdSchema,
2939
+ source_id: IdSchema,
2940
+ revision_key: z4.string().trim().min(1).max(500),
2941
+ content_sha256: Sha256Schema2.nullable(),
2942
+ source_updated_at: IsoDateTimeSchema2.nullable(),
2943
+ observed_at: IsoDateTimeSchema2,
2944
+ metadata: z4.record(z4.unknown())
2945
+ }).strict();
2946
+ CatalogProfileSchema = z4.object({
2947
+ id: IdSchema,
2948
+ profile_type: CatalogProfileTypeSchema,
2949
+ handle: CatalogSlugSchema,
2950
+ display_name: z4.string().trim().min(1).max(200),
2951
+ summary: z4.string().max(2e3).nullable(),
2952
+ avatar_url: UrlSchema.nullable(),
2953
+ canonical_source_revision_id: IdSchema,
2954
+ publication_state: CatalogPublicationStateSchema,
2955
+ published_at: IsoDateTimeSchema2.nullable(),
2956
+ withdrawn_at: IsoDateTimeSchema2.nullable()
2957
+ }).strict().superRefine((profile, context) => {
2958
+ if (profile.publication_state === "published" && profile.published_at === null) {
2959
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["published_at"], message: "published Profiles require published_at" });
2960
+ }
2961
+ if (profile.publication_state === "withdrawn" && profile.withdrawn_at === null) {
2962
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["withdrawn_at"], message: "withdrawn Profiles require withdrawn_at" });
2963
+ }
2964
+ });
2965
+ CatalogPersonSchema = z4.object({
2966
+ profile_id: IdSchema,
2967
+ public_name: z4.string().trim().min(1).max(200),
2968
+ headline: z4.string().max(500).nullable()
2969
+ }).strict();
2970
+ CatalogCompanySchema = z4.object({
2971
+ profile_id: IdSchema,
2972
+ legal_name: z4.string().trim().min(1).max(300).nullable(),
2973
+ website_url: UrlSchema.nullable(),
2974
+ is_publisher: z4.boolean()
2975
+ }).strict();
2976
+ CatalogSkillSchema = z4.object({
2977
+ id: IdSchema,
2978
+ slug: CatalogSlugSchema,
2979
+ title: z4.string().trim().min(1).max(200),
2980
+ summary: z4.string().max(2e3).nullable(),
2981
+ outcome: z4.string().max(2e3).nullable(),
2982
+ canonical_source_id: IdSchema,
2983
+ primary_creator_profile_id: IdSchema.nullable(),
2984
+ publisher_profile_id: IdSchema.nullable(),
2985
+ distribution_skill_id: IdSchema.nullable(),
2986
+ distribution_workspace_id: IdSchema.nullable(),
2987
+ canonical_release_id: IdSchema.nullable(),
2988
+ publication_state: CatalogPublicationStateSchema,
2989
+ published_at: IsoDateTimeSchema2.nullable(),
2990
+ withdrawn_at: IsoDateTimeSchema2.nullable()
2991
+ }).strict().superRefine((skill, context) => {
2992
+ if (skill.publication_state === "published") {
2993
+ for (const key of ["publisher_profile_id", "distribution_skill_id", "distribution_workspace_id", "canonical_release_id", "published_at"]) {
2994
+ if (skill[key] === null) context.addIssue({ code: z4.ZodIssueCode.custom, path: [key], message: `published Skills require ${key}` });
2995
+ }
2996
+ }
2997
+ if (skill.publication_state === "withdrawn" && skill.withdrawn_at === null) {
2998
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["withdrawn_at"], message: "withdrawn Skills require withdrawn_at" });
2999
+ }
3000
+ });
3001
+ CatalogReleaseSchema = z4.object({
3002
+ id: IdSchema,
3003
+ skill_id: IdSchema,
3004
+ source_revision_id: IdSchema,
3005
+ private_skill_version_id: IdSchema.nullable(),
3006
+ version: z4.string().trim().min(1).max(120),
3007
+ content_sha256: Sha256Schema2,
3008
+ publication_state: CatalogPublicationStateSchema,
3009
+ published_at: IsoDateTimeSchema2.nullable(),
3010
+ withdrawn_at: IsoDateTimeSchema2.nullable()
3011
+ }).strict().superRefine((release2, context) => {
3012
+ if (release2.publication_state === "published" && (release2.published_at === null || release2.private_skill_version_id === null)) {
3013
+ context.addIssue({
3014
+ code: z4.ZodIssueCode.custom,
3015
+ path: ["published_at"],
3016
+ message: "published releases require published_at and an immutable private Skill version"
3017
+ });
3018
+ }
3019
+ if (release2.publication_state === "withdrawn" && release2.withdrawn_at === null) {
3020
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["withdrawn_at"], message: "withdrawn Releases require withdrawn_at" });
3021
+ }
3022
+ });
3023
+ CatalogStackSchema = z4.object({
3024
+ id: IdSchema,
3025
+ slug: CatalogSlugSchema,
3026
+ title: z4.string().trim().min(1).max(200),
3027
+ summary: z4.string().max(2e3).nullable(),
3028
+ curator_profile_id: IdSchema,
3029
+ canonical_stack_version_id: IdSchema.nullable(),
3030
+ publication_state: CatalogPublicationStateSchema,
3031
+ published_at: IsoDateTimeSchema2.nullable(),
3032
+ withdrawn_at: IsoDateTimeSchema2.nullable()
3033
+ }).strict().superRefine((stack, context) => {
3034
+ if (stack.publication_state === "published" && (stack.canonical_stack_version_id === null || stack.published_at === null)) {
3035
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["canonical_stack_version_id"], message: "published Stacks require a canonical version and published_at" });
3036
+ }
3037
+ if (stack.publication_state === "withdrawn" && stack.withdrawn_at === null) {
3038
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["withdrawn_at"], message: "withdrawn Stacks require withdrawn_at" });
3039
+ }
3040
+ });
3041
+ CatalogStackVersionSchema = z4.object({
3042
+ id: IdSchema,
3043
+ stack_id: IdSchema,
3044
+ version_seq: z4.number().int().positive(),
3045
+ rationale: z4.string().trim().min(1).max(4e3),
3046
+ source_revision_id: IdSchema.nullable(),
3047
+ publication_state: CatalogPublicationStateSchema,
3048
+ published_at: IsoDateTimeSchema2.nullable(),
3049
+ withdrawn_at: IsoDateTimeSchema2.nullable()
3050
+ }).strict().superRefine((version, context) => {
3051
+ if (version.publication_state === "published" && version.published_at === null) {
3052
+ context.addIssue({
3053
+ code: z4.ZodIssueCode.custom,
3054
+ path: ["published_at"],
3055
+ message: "published Stack versions require published_at"
3056
+ });
3057
+ }
3058
+ if (version.publication_state === "published" && version.source_revision_id === null) {
3059
+ context.addIssue({
3060
+ code: z4.ZodIssueCode.custom,
3061
+ path: ["source_revision_id"],
3062
+ message: "published Stack versions require a source revision"
3063
+ });
3064
+ }
3065
+ if (version.publication_state === "withdrawn" && version.withdrawn_at === null) {
3066
+ context.addIssue({
3067
+ code: z4.ZodIssueCode.custom,
3068
+ path: ["withdrawn_at"],
3069
+ message: "withdrawn Stack versions require withdrawn_at"
3070
+ });
3071
+ }
3072
+ });
3073
+ CatalogTaxonomyAxisSchema = z4.enum([
3074
+ "capability",
3075
+ "task",
3076
+ "domain",
3077
+ "workflow_stage",
3078
+ "input",
3079
+ "output",
3080
+ "audience",
3081
+ "modality",
3082
+ "runtime",
3083
+ "integration"
3084
+ ]);
3085
+ CatalogAssignmentSourceSchema = z4.enum([
3086
+ "imported",
3087
+ "publisher",
3088
+ "model_assisted",
3089
+ "reviewer",
3090
+ "floom"
3091
+ ]);
3092
+ CatalogEvidenceClassSchema = z4.enum([
3093
+ "declared_fact",
3094
+ "inferred_assertion",
3095
+ "observed_evidence"
3096
+ ]);
3097
+ CatalogSkillLabelSchema = z4.object({
3098
+ skill_id: IdSchema,
3099
+ release_id: IdSchema.nullable(),
3100
+ source_revision_id: IdSchema.nullable(),
3101
+ label_id: IdSchema,
3102
+ axis: CatalogTaxonomyAxisSchema,
3103
+ taxonomy_version_id: IdSchema,
3104
+ label_role: z4.enum(["primary", "secondary"]),
3105
+ assignment_source: CatalogAssignmentSourceSchema,
3106
+ evidence_class: CatalogEvidenceClassSchema,
3107
+ confidence: z4.number().min(0).max(1).nullable(),
3108
+ classifier_version: z4.string().min(1).nullable(),
3109
+ prompt_version: z4.string().min(1).nullable(),
3110
+ input_content_sha256: Sha256Schema2.nullable(),
3111
+ reviewer_id: IdSchema.nullable(),
3112
+ reviewed_at: IsoDateTimeSchema2.nullable()
3113
+ }).strict().superRefine((assignment, context) => {
3114
+ if (assignment.release_id === null === (assignment.source_revision_id === null)) {
3115
+ context.addIssue({
3116
+ code: z4.ZodIssueCode.custom,
3117
+ path: ["release_id"],
3118
+ message: "exactly one release_id or source_revision_id is required"
3119
+ });
3120
+ }
3121
+ if (assignment.label_role === "primary" && !["capability", "task"].includes(assignment.axis)) {
3122
+ context.addIssue({
3123
+ code: z4.ZodIssueCode.custom,
3124
+ path: ["label_role"],
3125
+ message: "only capability and task labels can be primary"
3126
+ });
3127
+ }
3128
+ if (assignment.assignment_source === "model_assisted") {
3129
+ const hasModelProvenance = assignment.evidence_class === "inferred_assertion" && assignment.confidence !== null && assignment.classifier_version !== null && assignment.prompt_version !== null && assignment.input_content_sha256 !== null;
3130
+ if (!hasModelProvenance) {
3131
+ context.addIssue({
3132
+ code: z4.ZodIssueCode.custom,
3133
+ path: ["assignment_source"],
3134
+ message: "model-assisted labels require complete inference provenance"
3135
+ });
3136
+ }
3137
+ }
3138
+ if (assignment.reviewer_id !== null && assignment.reviewed_at === null) {
3139
+ context.addIssue({
3140
+ code: z4.ZodIssueCode.custom,
3141
+ path: ["reviewed_at"],
3142
+ message: "reviewed labels require reviewed_at"
3143
+ });
3144
+ }
3145
+ });
3146
+ CatalogCompatibilitySchema = z4.object({
3147
+ release_id: IdSchema,
3148
+ target_type: z4.enum(["runtime", "integration", "operating_system", "tool"]),
3149
+ target_slug: z4.string().regex(/^[a-z0-9][a-z0-9._-]{0,79}$/),
3150
+ compatibility_state: z4.enum(["unknown", "supported", "unsupported", "verified"]),
3151
+ install_method: z4.string().min(1).max(120).nullable(),
3152
+ evidence_id: IdSchema.nullable(),
3153
+ verified_at: IsoDateTimeSchema2.nullable()
3154
+ }).strict().superRefine((compatibility, context) => {
3155
+ if (compatibility.compatibility_state === "verified" && (compatibility.evidence_id === null || compatibility.verified_at === null)) {
3156
+ context.addIssue({
3157
+ code: z4.ZodIssueCode.custom,
3158
+ path: ["compatibility_state"],
3159
+ message: "verified compatibility requires evidence and verified_at"
3160
+ });
3161
+ }
3162
+ });
3163
+ CatalogPermissionSchema = z4.object({
3164
+ release_id: IdSchema,
3165
+ permission_key: z4.string().regex(/^[a-z][a-z0-9._-]{1,79}$/),
3166
+ access_mode: z4.enum(["read", "write", "execute", "send"]),
3167
+ required: z4.boolean(),
3168
+ approval_mode: z4.enum(["none", "per_action", "session", "external"]),
3169
+ data_sensitivity: z4.enum(["public", "internal", "confidential", "restricted"]),
3170
+ description: z4.string().max(2e3).nullable(),
3171
+ evidence_id: IdSchema.nullable()
3172
+ }).strict();
3173
+ CatalogEvidenceEventSchema = z4.object({
3174
+ id: IdSchema,
3175
+ evidence_id: IdSchema,
3176
+ event_type: z4.enum(["recorded", "published", "withdrawn"]),
3177
+ prior_event_id: IdSchema.nullable(),
3178
+ actor_id: IdSchema.nullable(),
3179
+ reason: z4.string().trim().min(1).max(2e3).nullable(),
3180
+ occurred_at: IsoDateTimeSchema2
3181
+ }).strict().superRefine((event, context) => {
3182
+ if (event.event_type === "recorded" && event.prior_event_id !== null) {
3183
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["prior_event_id"], message: "recorded is the root event" });
3184
+ }
3185
+ if (event.event_type !== "recorded" && event.prior_event_id === null) {
3186
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["prior_event_id"], message: "non-root evidence events require prior_event_id" });
3187
+ }
3188
+ if (event.event_type === "withdrawn" && event.reason === null) {
3189
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["reason"], message: "withdrawal requires a reason" });
3190
+ }
3191
+ });
3192
+ CatalogRightsEventSchema = z4.object({
3193
+ id: IdSchema,
3194
+ release_id: IdSchema,
3195
+ event_type: z4.enum(["grant", "supersession", "withdrawal", "expiry"]),
3196
+ rights_state: z4.enum(["allowed", "restricted", "prohibited", "withdrawn", "expired"]),
3197
+ rights_basis: z4.enum(["license", "direct_permission", "public_domain", "ownership"]).nullable(),
3198
+ scopes: z4.array(z4.enum(["distribution", "redistribution", "display", "evaluation"])).min(0),
3199
+ evidence_id: IdSchema,
3200
+ prior_event_id: IdSchema.nullable(),
3201
+ effective_at: IsoDateTimeSchema2,
3202
+ expires_at: IsoDateTimeSchema2.nullable()
3203
+ }).strict().superRefine((rights, context) => {
3204
+ const grantsRights = ["grant", "supersession"].includes(rights.event_type);
3205
+ if (grantsRights && (rights.rights_basis === null || rights.scopes.length === 0)) {
3206
+ context.addIssue({
3207
+ code: z4.ZodIssueCode.custom,
3208
+ path: ["rights_basis"],
3209
+ message: "grant and supersession require a basis and explicit scopes"
3210
+ });
3211
+ }
3212
+ if (!grantsRights && (rights.rights_basis !== null || rights.scopes.length !== 0)) {
3213
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["scopes"], message: "withdrawal and expiry do not grant scopes" });
3214
+ }
3215
+ if (rights.event_type === "grant" && rights.prior_event_id !== null) {
3216
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["prior_event_id"], message: "grant is the root rights event" });
3217
+ }
3218
+ if (rights.event_type !== "grant" && rights.prior_event_id === null) {
3219
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["prior_event_id"], message: "non-root rights events require prior_event_id" });
3220
+ }
3221
+ const expectedState = rights.event_type === "withdrawal" ? "withdrawn" : rights.event_type === "expiry" ? "expired" : null;
3222
+ if (expectedState !== null && rights.rights_state !== expectedState) {
3223
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["rights_state"], message: `${rights.event_type} requires ${expectedState}` });
3224
+ }
3225
+ if (grantsRights && !["allowed", "restricted", "prohibited"].includes(rights.rights_state)) {
3226
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["rights_state"], message: "granting events require an asserted rights state" });
3227
+ }
3228
+ if (rights.expires_at !== null && Date.parse(rights.expires_at) <= Date.parse(rights.effective_at)) {
3229
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["expires_at"], message: "rights expiry must follow its effective time" });
3230
+ }
3231
+ });
3232
+ CatalogTrustAssertionSchema = z4.object({
3233
+ id: IdSchema,
3234
+ assertion_type: z4.enum(["signed_by", "tested", "evaluated", "recommended"]),
3235
+ profile_id: IdSchema.nullable(),
3236
+ skill_id: IdSchema.nullable(),
3237
+ release_id: IdSchema.nullable(),
3238
+ release_content_sha256: Sha256Schema2.nullable(),
3239
+ issuer_profile_id: IdSchema,
3240
+ issuer_verification_evidence_id: IdSchema.nullable(),
3241
+ issuer_identity_verification_record_id: IdSchema.nullable(),
3242
+ evidence_id: IdSchema,
3243
+ install_evidence_id: IdSchema.nullable(),
3244
+ agent: z4.string().trim().min(1).max(120).nullable(),
3245
+ runtime: z4.string().trim().min(1).max(120).nullable(),
3246
+ test_name: z4.string().trim().min(1).max(200).nullable(),
3247
+ eval_suite: z4.string().trim().min(1).max(200).nullable(),
3248
+ eval_suite_version: z4.string().trim().min(1).max(120).nullable(),
3249
+ result: z4.string().trim().min(1).max(500).nullable(),
3250
+ score: z4.number().finite().nullable(),
3251
+ recommendation_statement: z4.string().trim().min(1).max(2e3).nullable(),
3252
+ asserted_at: IsoDateTimeSchema2,
3253
+ proposed_by: IdSchema,
3254
+ public_explanation: z4.string().trim().min(1).max(2e3)
3255
+ }).strict().superRefine((assertion, context) => {
3256
+ if ([assertion.profile_id, assertion.skill_id, assertion.release_id].filter((value) => value !== null).length !== 1) {
3257
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["release_id"], message: "exactly one Trust subject is required" });
3258
+ }
3259
+ const releaseBound = ["signed_by", "tested", "evaluated"].includes(assertion.assertion_type);
3260
+ if (releaseBound && (assertion.release_id === null || assertion.release_content_sha256 === null)) {
3261
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["release_id"], message: "release-bound Trust requires exact Release and hash" });
3262
+ }
3263
+ if (assertion.assertion_type === "signed_by" && (assertion.issuer_verification_evidence_id === null || assertion.issuer_identity_verification_record_id === null)) {
3264
+ context.addIssue({
3265
+ code: z4.ZodIssueCode.custom,
3266
+ path: ["issuer_identity_verification_record_id"],
3267
+ message: "Signed by requires verified issuer evidence and an active Identity Verification Record"
3268
+ });
3269
+ }
3270
+ if (assertion.assertion_type === "tested" && (assertion.install_evidence_id === null || assertion.agent === null || assertion.runtime === null || assertion.test_name === null || assertion.result !== "passed")) {
3271
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["result"], message: "Tested requires agent, runtime, named smoke test, and passed result" });
3272
+ }
3273
+ if (assertion.assertion_type === "evaluated" && (assertion.eval_suite === null || assertion.eval_suite_version === null || assertion.result === null)) {
3274
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["eval_suite"], message: "Evaluated requires named versioned suite and result" });
3275
+ }
3276
+ if (assertion.assertion_type === "recommended" && assertion.recommendation_statement === null) {
3277
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["recommendation_statement"], message: "Recommended requires an explicit statement" });
3278
+ }
3279
+ });
3280
+ CatalogTrustAssertionEventSchema = z4.object({
3281
+ id: IdSchema,
3282
+ assertion_id: IdSchema,
3283
+ status: z4.enum(["draft", "active", "disputed", "suspended", "withdrawn", "expired"]),
3284
+ prior_event_id: IdSchema.nullable(),
3285
+ reviewer_id: IdSchema.nullable(),
3286
+ review_method: z4.string().trim().min(1).max(500).nullable(),
3287
+ reason: z4.string().trim().min(1).max(2e3).nullable(),
3288
+ occurred_at: IsoDateTimeSchema2
3289
+ }).strict().superRefine((event, context) => {
3290
+ if (event.status === "draft" && event.prior_event_id !== null) {
3291
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["prior_event_id"], message: "draft is the root Trust event" });
3292
+ }
3293
+ if (event.status !== "draft" && event.prior_event_id === null) {
3294
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["prior_event_id"], message: "non-draft Trust events require prior_event_id" });
3295
+ }
3296
+ if (event.status === "active" && (event.reviewer_id === null || event.review_method === null)) {
3297
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["reviewer_id"], message: "active Trust requires review evidence" });
3298
+ }
3299
+ if (["disputed", "suspended", "withdrawn", "expired"].includes(event.status) && event.reason === null) {
3300
+ context.addIssue({ code: z4.ZodIssueCode.custom, path: ["reason"], message: `${event.status} requires a reason` });
3301
+ }
3302
+ });
3303
+ }
3304
+ });
3305
+
3306
+ // ../shared/src/catalog-trust.ts
3307
+ import { z as z5 } from "zod";
3308
+ function addUtcMonthsClamped(value, months) {
3309
+ const source = new Date(value);
3310
+ const result = new Date(source);
3311
+ const day = result.getUTCDate();
3312
+ result.setUTCDate(1);
3313
+ result.setUTCMonth(result.getUTCMonth() + months);
3314
+ const finalDay = new Date(Date.UTC(result.getUTCFullYear(), result.getUTCMonth() + 1, 0)).getUTCDate();
3315
+ result.setUTCDate(Math.min(day, finalDay));
3316
+ return result.getTime();
3317
+ }
3318
+ var CatalogContractAuthoritySchema, CatalogProfileClaimIntentSchema, CatalogProfileClaimRequestStateSchema, CatalogProfileControlStateSchema, CatalogIdentityVerificationRequestStateSchema, CatalogIdentityVerificationRecordStateSchema, CatalogGovernanceScopeSchema, CatalogMethodVersionStateSchema, Ed25519PublicKeySchema2, Ed25519SignatureSchema2, CatalogTrustAuthorityRootSchema, CatalogTrustReviewerAssignmentSchema, CatalogTrustReviewerAssignmentEventSchema, CatalogMethodVersionBaseSchema, CatalogProfileClaimMethodVersionSchema, CatalogIdentityVerificationMethodVersionSchema, CatalogMethodVersionEventSchema, CatalogProfileClaimChallengeSchema, CatalogProfileClaimRequestSchema, CatalogProfileClaimEvidenceReferenceSchema, CatalogWorkflowEventBaseSchema, CatalogProfileClaimRequestEventSchema, CatalogProfileControlEventSchema, CatalogProfileControlSchema, CatalogIdentityVerificationRequestSchema, CatalogIdentityVerificationRequestEventSchema, CatalogIdentityEvidenceReferenceSchema, CatalogIdentityVerificationChallengeSchema, CatalogIdentityVerificationResultSchema, CatalogPrivateEvidenceRetentionEventSchema, CatalogPrivateEvidenceLegalHoldEventSchema, CatalogPrivateEvidenceDeletionReceiptSchema, CatalogIdentityVerificationRecordSchema, CatalogIdentityVerificationRecordEventSchema;
3319
+ var init_catalog_trust = __esm({
3320
+ "../shared/src/catalog-trust.ts"() {
3321
+ "use strict";
3322
+ init_contract();
3323
+ CatalogContractAuthoritySchema = z5.literal(
3324
+ "agent_proposed_reviewer_verified"
3325
+ );
3326
+ CatalogProfileClaimIntentSchema = z5.enum([
3327
+ "initial",
3328
+ "reclaim",
3329
+ "transfer"
3330
+ ]);
3331
+ CatalogProfileClaimRequestStateSchema = z5.enum([
3332
+ "claim_requested",
3333
+ "challenge_issued",
3334
+ "proof_submitted",
3335
+ "under_review",
3336
+ "approved",
3337
+ "rejected",
3338
+ "expired",
3339
+ "withdrawn",
3340
+ "superseded"
3341
+ ]);
3342
+ CatalogProfileControlStateSchema = z5.enum([
3343
+ "active",
3344
+ "disputed",
3345
+ "transferred",
3346
+ "withdrawn",
3347
+ "expired"
3348
+ ]);
3349
+ CatalogIdentityVerificationRequestStateSchema = z5.enum([
3350
+ "verification_requested",
3351
+ "challenge_issued",
3352
+ "proof_submitted",
3353
+ "under_review",
3354
+ "approved",
3355
+ "rejected",
3356
+ "expired",
3357
+ "withdrawn",
3358
+ "superseded"
3359
+ ]);
3360
+ CatalogIdentityVerificationRecordStateSchema = z5.enum([
3361
+ "active",
3362
+ "suspended",
3363
+ "revoked",
3364
+ "expired"
3365
+ ]);
3366
+ CatalogGovernanceScopeSchema = z5.literal("catalog_trust_governance");
3367
+ CatalogMethodVersionStateSchema = z5.enum(["proposed", "active", "retired"]);
3368
+ Ed25519PublicKeySchema2 = z5.string().regex(/^[A-Za-z0-9+/]{43}=$/);
3369
+ Ed25519SignatureSchema2 = z5.string().regex(/^[A-Za-z0-9+/]{86}==$/);
3370
+ CatalogTrustAuthorityRootSchema = z5.object({
3371
+ id: IdSchema,
3372
+ authority_scope: CatalogGovernanceScopeSchema,
3373
+ authority_reference: z5.string().trim().min(1).max(2e3),
3374
+ authority_sha256: Sha256Schema2,
3375
+ anchor_key_id: z5.string().regex(/^[a-z0-9][a-z0-9._:-]{0,119}$/),
3376
+ authority_public_key: Ed25519PublicKeySchema2,
3377
+ anchor_signature: Ed25519SignatureSchema2,
3378
+ active_from: IsoDateTimeSchema2,
3379
+ created_at: IsoDateTimeSchema2
3380
+ }).strict();
3381
+ CatalogTrustReviewerAssignmentSchema = z5.object({
3382
+ id: IdSchema,
3383
+ authority_root_id: IdSchema,
3384
+ authority_scope: CatalogGovernanceScopeSchema,
3385
+ reviewer_id: IdSchema,
3386
+ assignment_role: z5.enum(["trust_reviewer", "backup_trust_reviewer"]),
3387
+ appointed_by: IdSchema,
3388
+ authority_reference: z5.string().trim().min(1).max(2e3),
3389
+ authority_sha256: Sha256Schema2,
3390
+ valid_from: IsoDateTimeSchema2,
3391
+ valid_until: IsoDateTimeSchema2,
3392
+ current_state: z5.enum(["active", "revoked", "expired"]),
3393
+ terminal_at: IsoDateTimeSchema2.nullable(),
3394
+ created_at: IsoDateTimeSchema2
3395
+ }).strict().superRefine((assignment, context) => {
3396
+ if (assignment.reviewer_id === assignment.appointed_by) {
3397
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["appointed_by"], message: "reviewers cannot appoint themselves" });
3398
+ }
3399
+ if (Date.parse(assignment.valid_until) <= Date.parse(assignment.valid_from)) {
3400
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["valid_until"], message: "valid_until must follow valid_from" });
3401
+ }
3402
+ if (Date.parse(assignment.valid_until) > Date.parse(assignment.valid_from) + 365 * 24 * 60 * 60 * 1e3) {
3403
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["valid_until"], message: "assignment exceeds its one-year bound" });
3404
+ }
3405
+ const terminal = assignment.current_state !== "active";
3406
+ if (terminal !== (assignment.terminal_at !== null)) {
3407
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["terminal_at"], message: "terminal_at must match assignment state" });
3408
+ }
3409
+ });
3410
+ CatalogTrustReviewerAssignmentEventSchema = z5.object({
3411
+ id: IdSchema,
3412
+ assignment_id: IdSchema,
3413
+ state: z5.enum(["active", "revoked", "expired"]),
3414
+ prior_event_id: IdSchema.nullable(),
3415
+ actor_id: IdSchema,
3416
+ authority_root_id: IdSchema,
3417
+ reason: z5.string().trim().min(1).max(2e3),
3418
+ occurred_at: IsoDateTimeSchema2,
3419
+ created_at: IsoDateTimeSchema2
3420
+ }).strict().superRefine((event, context) => {
3421
+ if (event.state === "active" !== (event.prior_event_id === null)) {
3422
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["prior_event_id"], message: "assignment history begins once with active" });
3423
+ }
3424
+ });
3425
+ CatalogMethodVersionBaseSchema = z5.object({
3426
+ id: IdSchema,
3427
+ version: z5.string().trim().min(1).max(120),
3428
+ contract_authority: CatalogContractAuthoritySchema,
3429
+ configuration_sha256: Sha256Schema2,
3430
+ activated_at: IsoDateTimeSchema2.nullable(),
3431
+ retired_at: IsoDateTimeSchema2.nullable(),
3432
+ proposed_by: IdSchema,
3433
+ reviewed_by: IdSchema.nullable(),
3434
+ current_state: CatalogMethodVersionStateSchema,
3435
+ created_at: IsoDateTimeSchema2
3436
+ }).strict();
3437
+ CatalogProfileClaimMethodVersionSchema = CatalogMethodVersionBaseSchema.extend({
3438
+ method: z5.enum(["corporate_domain_email", "operator_direct_relationship"])
3439
+ }).superRefine((method, context) => {
3440
+ if (method.reviewed_by !== null && method.proposed_by === method.reviewed_by) {
3441
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["reviewed_by"], message: "method review must be independent" });
3442
+ }
3443
+ if (method.retired_at !== null && method.activated_at !== null && Date.parse(method.retired_at) <= Date.parse(method.activated_at)) {
3444
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["retired_at"], message: "retired_at must follow activated_at" });
3445
+ }
3446
+ const validState = method.current_state === "proposed" && method.activated_at === null && method.retired_at === null && method.reviewed_by === null || method.current_state === "active" && method.activated_at !== null && method.retired_at === null && method.reviewed_by !== null || method.current_state === "retired" && method.activated_at !== null && method.retired_at !== null && method.reviewed_by !== null;
3447
+ if (!validState) context.addIssue({ code: z5.ZodIssueCode.custom, path: ["current_state"], message: "method lifecycle fields are inconsistent" });
3448
+ });
3449
+ CatalogIdentityVerificationMethodVersionSchema = CatalogMethodVersionBaseSchema.extend({
3450
+ subject_kind: z5.enum(["person", "publisher"])
3451
+ }).superRefine((method, context) => {
3452
+ if (method.reviewed_by !== null && method.proposed_by === method.reviewed_by) {
3453
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["reviewed_by"], message: "method review must be independent" });
3454
+ }
3455
+ if (method.retired_at !== null && method.activated_at !== null && Date.parse(method.retired_at) <= Date.parse(method.activated_at)) {
3456
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["retired_at"], message: "retired_at must follow activated_at" });
3457
+ }
3458
+ const validState = method.current_state === "proposed" && method.activated_at === null && method.retired_at === null && method.reviewed_by === null || method.current_state === "active" && method.activated_at !== null && method.retired_at === null && method.reviewed_by !== null || method.current_state === "retired" && method.activated_at !== null && method.retired_at !== null && method.reviewed_by !== null;
3459
+ if (!validState) context.addIssue({ code: z5.ZodIssueCode.custom, path: ["current_state"], message: "method lifecycle fields are inconsistent" });
3460
+ });
3461
+ CatalogMethodVersionEventSchema = z5.object({
3462
+ id: IdSchema,
3463
+ method_version_id: IdSchema,
3464
+ state: CatalogMethodVersionStateSchema,
3465
+ prior_event_id: IdSchema.nullable(),
3466
+ actor_id: IdSchema,
3467
+ reviewer_id: IdSchema.nullable(),
3468
+ reason: z5.string().trim().min(1).max(2e3),
3469
+ occurred_at: IsoDateTimeSchema2,
3470
+ created_at: IsoDateTimeSchema2
3471
+ }).strict().superRefine((event, context) => {
3472
+ if (event.state === "proposed" !== (event.prior_event_id === null)) {
3473
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["prior_event_id"], message: "method history begins once with proposed" });
3474
+ }
3475
+ if (event.state !== "proposed" && (event.reviewer_id === null || event.actor_id !== event.reviewer_id)) {
3476
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["reviewer_id"], message: "method decisions require the acting reviewer" });
3477
+ }
3478
+ });
3479
+ CatalogProfileClaimChallengeSchema = z5.object({
3480
+ id: IdSchema,
3481
+ claim_request_id: IdSchema,
3482
+ challenge_secret_hash: Sha256Schema2,
3483
+ binding_sha256: Sha256Schema2,
3484
+ issued_at: IsoDateTimeSchema2,
3485
+ expires_at: IsoDateTimeSchema2,
3486
+ consumed_at: IsoDateTimeSchema2.nullable(),
3487
+ purge_after: IsoDateTimeSchema2,
3488
+ created_at: IsoDateTimeSchema2
3489
+ }).strict().superRefine((challenge, context) => {
3490
+ const issued = Date.parse(challenge.issued_at);
3491
+ if (Date.parse(challenge.expires_at) !== issued + 30 * 60 * 1e3) {
3492
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["expires_at"], message: "challenge expires exactly 30 minutes after issuance" });
3493
+ }
3494
+ if (Date.parse(challenge.purge_after) !== issued + 30 * 24 * 60 * 60 * 1e3) {
3495
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["purge_after"], message: "challenge purges exactly 30 days after issuance" });
3496
+ }
3497
+ if (challenge.consumed_at !== null) {
3498
+ const consumed = Date.parse(challenge.consumed_at);
3499
+ if (consumed < issued || consumed > Date.parse(challenge.expires_at)) {
3500
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["consumed_at"], message: "consumption must occur during challenge validity" });
3501
+ }
3502
+ }
3503
+ });
3504
+ CatalogProfileClaimRequestSchema = z5.object({
3505
+ id: IdSchema,
3506
+ profile_id: IdSchema,
3507
+ claimant_user_id: IdSchema,
3508
+ proposed_controller_user_id: IdSchema,
3509
+ intent: CatalogProfileClaimIntentSchema,
3510
+ actor_capacity: z5.enum([
3511
+ "person",
3512
+ "company_representative",
3513
+ "publisher_representative"
3514
+ ]),
3515
+ method_version_id: IdSchema,
3516
+ prior_profile_control_id: IdSchema.nullable(),
3517
+ transfer_authorization_type: z5.enum(["controller_consent", "dispute_resolution"]).nullable(),
3518
+ transfer_authorization_sha256: Sha256Schema2.nullable(),
3519
+ transfer_consent_event_id: IdSchema.nullable(),
3520
+ transfer_dispute_record_id: IdSchema.nullable(),
3521
+ current_state: CatalogProfileClaimRequestStateSchema,
3522
+ created_at: IsoDateTimeSchema2,
3523
+ terminal_at: IsoDateTimeSchema2.nullable()
3524
+ }).strict().superRefine((request, context) => {
3525
+ const terminal = ["approved", "rejected", "expired", "withdrawn", "superseded"].includes(
3526
+ request.current_state
3527
+ );
3528
+ if (terminal !== (request.terminal_at !== null)) {
3529
+ context.addIssue({
3530
+ code: z5.ZodIssueCode.custom,
3531
+ path: ["terminal_at"],
3532
+ message: "terminal_at must match terminal Claim Request state"
3533
+ });
3534
+ }
3535
+ const transferFields = [
3536
+ request.prior_profile_control_id,
3537
+ request.transfer_authorization_type,
3538
+ request.transfer_authorization_sha256
3539
+ ];
3540
+ if (request.intent === "transfer" && transferFields.some((value) => value === null) || request.intent !== "transfer" && transferFields.some((value) => value !== null)) {
3541
+ context.addIssue({
3542
+ code: z5.ZodIssueCode.custom,
3543
+ path: ["intent"],
3544
+ message: "transfer bindings are required only for transfer requests"
3545
+ });
3546
+ }
3547
+ const recordBindings = [request.transfer_consent_event_id, request.transfer_dispute_record_id];
3548
+ if (request.intent !== "transfer" && recordBindings.some((value) => value !== null)) {
3549
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["intent"], message: "authorization records belong only to transfers" });
3550
+ }
3551
+ if (request.intent === "transfer") {
3552
+ const consent = request.transfer_authorization_type === "controller_consent";
3553
+ if (consent && (request.transfer_consent_event_id === null || request.transfer_dispute_record_id !== null) || !consent && (request.transfer_consent_event_id !== null || request.transfer_dispute_record_id === null)) {
3554
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["transfer_authorization_type"], message: "transfer authorization must bind exactly one matching record" });
3555
+ }
3556
+ }
3557
+ });
3558
+ CatalogProfileClaimEvidenceReferenceSchema = z5.object({
3559
+ id: IdSchema,
3560
+ claim_request_id: IdSchema,
3561
+ evidence_class: z5.enum([
3562
+ "corporate_domain_control",
3563
+ "authenticated_channel",
3564
+ "corroborating_relationship",
3565
+ "reviewer_evidence",
3566
+ "malformed_proof"
3567
+ ]),
3568
+ private_reference: z5.string().regex(/^private:\/\/[^\s]+$/).max(2e3),
3569
+ reference_sha256: Sha256Schema2,
3570
+ submitted_by: IdSchema,
3571
+ created_at: IsoDateTimeSchema2,
3572
+ purge_after: IsoDateTimeSchema2,
3573
+ purge_claimed_at: IsoDateTimeSchema2.nullable(),
3574
+ purge_claim_token: IdSchema.nullable(),
3575
+ purge_attempt_count: z5.number().int().nonnegative()
3576
+ }).strict().superRefine((evidence, context) => {
3577
+ const created = new Date(evidence.created_at);
3578
+ const maximum = new Date(created);
3579
+ if (evidence.evidence_class === "malformed_proof") maximum.setUTCDate(maximum.getUTCDate() + 7);
3580
+ else maximum.setTime(addUtcMonthsClamped(evidence.created_at, 24));
3581
+ if (Date.parse(evidence.purge_after) < created.getTime() + 24 * 60 * 60 * 1e3) {
3582
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["purge_after"], message: "retention is below its one-day floor" });
3583
+ }
3584
+ if (Date.parse(evidence.purge_after) > maximum.getTime()) {
3585
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["purge_after"], message: "retention exceeds its evidence-class bound" });
3586
+ }
3587
+ if (evidence.purge_claimed_at === null !== (evidence.purge_claim_token === null)) {
3588
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["purge_claim_token"], message: "purge claim time and token must be paired" });
3589
+ }
3590
+ });
3591
+ CatalogWorkflowEventBaseSchema = z5.object({
3592
+ id: IdSchema,
3593
+ prior_event_id: IdSchema.nullable(),
3594
+ actor_id: IdSchema,
3595
+ reviewer_id: IdSchema.nullable(),
3596
+ evidence_manifest_sha256: Sha256Schema2.nullable(),
3597
+ reason: z5.string().trim().min(1).max(2e3).nullable(),
3598
+ occurred_at: IsoDateTimeSchema2,
3599
+ created_at: IsoDateTimeSchema2
2734
3600
  }).strict();
2735
- SkillSyncStateResponseSchema = z2.object({
2736
- machines: z2.array(SkillSyncMachineSchema),
2737
- total_machines: z2.number().int().nonnegative(),
2738
- total_targets_synced: z2.number().int().nonnegative()
3601
+ CatalogProfileClaimRequestEventSchema = CatalogWorkflowEventBaseSchema.extend({
3602
+ claim_request_id: IdSchema,
3603
+ state: CatalogProfileClaimRequestStateSchema
3604
+ }).superRefine((event, context) => {
3605
+ if (event.state === "claim_requested" !== (event.prior_event_id === null)) {
3606
+ context.addIssue({
3607
+ code: z5.ZodIssueCode.custom,
3608
+ path: ["prior_event_id"],
3609
+ message: "only claim_requested is a root event"
3610
+ });
3611
+ }
3612
+ if (["rejected", "expired", "withdrawn", "superseded"].includes(event.state) && event.reason === null) {
3613
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["reason"], message: `${event.state} requires a reason` });
3614
+ }
3615
+ });
3616
+ CatalogProfileControlEventSchema = CatalogWorkflowEventBaseSchema.extend({
3617
+ profile_control_id: IdSchema,
3618
+ state: CatalogProfileControlStateSchema
3619
+ }).superRefine((event, context) => {
3620
+ if (event.prior_event_id === null && event.state !== "active") {
3621
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["prior_event_id"], message: "Profile Control history must begin with active" });
3622
+ }
3623
+ if (event.state !== "active" && event.reason === null) {
3624
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["reason"], message: `${event.state} requires a reason` });
3625
+ }
3626
+ });
3627
+ CatalogProfileControlSchema = z5.object({
3628
+ id: IdSchema,
3629
+ profile_id: IdSchema,
3630
+ controller_user_id: IdSchema,
3631
+ claim_request_id: IdSchema,
3632
+ current_state: CatalogProfileControlStateSchema,
3633
+ next_recheck_at: IsoDateTimeSchema2,
3634
+ created_at: IsoDateTimeSchema2,
3635
+ terminal_at: IsoDateTimeSchema2.nullable()
3636
+ }).strict().superRefine((control, context) => {
3637
+ const terminal = ["transferred", "withdrawn", "expired"].includes(control.current_state);
3638
+ if (terminal !== (control.terminal_at !== null)) {
3639
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["terminal_at"], message: "terminal_at must match terminal Profile Control state" });
3640
+ }
3641
+ });
3642
+ CatalogIdentityVerificationRequestSchema = z5.object({
3643
+ id: IdSchema,
3644
+ profile_id: IdSchema,
3645
+ profile_control_id: IdSchema,
3646
+ claimant_user_id: IdSchema,
3647
+ evidence_proposer_id: IdSchema,
3648
+ subject_kind: z5.enum(["person", "publisher"]),
3649
+ method_version_id: IdSchema,
3650
+ current_state: CatalogIdentityVerificationRequestStateSchema,
3651
+ created_at: IsoDateTimeSchema2,
3652
+ terminal_at: IsoDateTimeSchema2.nullable()
3653
+ }).strict().superRefine((request, context) => {
3654
+ const terminal = ["approved", "rejected", "expired", "withdrawn", "superseded"].includes(request.current_state);
3655
+ if (terminal !== (request.terminal_at !== null)) {
3656
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["terminal_at"], message: "terminal_at must match terminal Identity Request state" });
3657
+ }
3658
+ });
3659
+ CatalogIdentityVerificationRequestEventSchema = CatalogWorkflowEventBaseSchema.extend({
3660
+ identity_verification_request_id: IdSchema,
3661
+ state: CatalogIdentityVerificationRequestStateSchema
3662
+ }).superRefine((event, context) => {
3663
+ if (event.state === "verification_requested" !== (event.prior_event_id === null)) {
3664
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["prior_event_id"], message: "only verification_requested is a root event" });
3665
+ }
3666
+ if (["rejected", "expired", "withdrawn", "superseded"].includes(event.state) && event.reason === null) {
3667
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["reason"], message: `${event.state} requires a reason` });
3668
+ }
3669
+ });
3670
+ CatalogIdentityEvidenceReferenceSchema = z5.object({
3671
+ id: IdSchema,
3672
+ identity_verification_request_id: IdSchema,
3673
+ evidence_kind: z5.enum([
3674
+ "government_photo_id",
3675
+ "live_face_match",
3676
+ "controlled_domain",
3677
+ "publishing_account",
3678
+ "derived_match",
3679
+ "reviewer_evidence"
3680
+ ]),
3681
+ private_reference: z5.string().regex(/^private:\/\/[^\s]+$/).max(2e3),
3682
+ reference_sha256: Sha256Schema2,
3683
+ derived_result: z5.string().trim().min(1).max(2e3).nullable(),
3684
+ submitted_by: IdSchema,
3685
+ created_at: IsoDateTimeSchema2,
3686
+ purge_after: IsoDateTimeSchema2,
3687
+ purge_claimed_at: IsoDateTimeSchema2.nullable(),
3688
+ purge_claim_token: IdSchema.nullable(),
3689
+ purge_attempt_count: z5.number().int().nonnegative()
3690
+ }).strict().superRefine((evidence, context) => {
3691
+ const created = new Date(evidence.created_at);
3692
+ const maximum = new Date(created);
3693
+ if (["government_photo_id", "live_face_match"].includes(evidence.evidence_kind)) {
3694
+ maximum.setUTCDate(maximum.getUTCDate() + 30);
3695
+ } else {
3696
+ maximum.setTime(addUtcMonthsClamped(evidence.created_at, 24));
3697
+ }
3698
+ if (Date.parse(evidence.purge_after) < created.getTime() + 24 * 60 * 60 * 1e3) {
3699
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["purge_after"], message: "retention is below its one-day floor" });
3700
+ }
3701
+ if (Date.parse(evidence.purge_after) > maximum.getTime()) {
3702
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["purge_after"], message: "retention exceeds its evidence-kind bound" });
3703
+ }
3704
+ if (evidence.purge_claimed_at === null !== (evidence.purge_claim_token === null)) {
3705
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["purge_claim_token"], message: "purge claim time and token must be paired" });
3706
+ }
3707
+ });
3708
+ CatalogIdentityVerificationChallengeSchema = z5.object({
3709
+ id: IdSchema,
3710
+ identity_verification_request_id: IdSchema,
3711
+ subject_kind: z5.enum(["person", "publisher"]),
3712
+ challenge_secret_hash: Sha256Schema2,
3713
+ binding_sha256: Sha256Schema2,
3714
+ issued_by: IdSchema,
3715
+ issued_at: IsoDateTimeSchema2,
3716
+ expires_at: IsoDateTimeSchema2,
3717
+ consumed_at: IsoDateTimeSchema2.nullable(),
3718
+ purge_after: IsoDateTimeSchema2,
3719
+ created_at: IsoDateTimeSchema2
3720
+ }).strict().superRefine((challenge, context) => {
3721
+ const issued = Date.parse(challenge.issued_at);
3722
+ if (Date.parse(challenge.expires_at) !== issued + 30 * 60 * 1e3) {
3723
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["expires_at"], message: "identity challenge expires after exactly 30 minutes" });
3724
+ }
3725
+ if (Date.parse(challenge.purge_after) !== issued + 30 * 24 * 60 * 60 * 1e3) {
3726
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["purge_after"], message: "identity challenge retention is exactly 30 days" });
3727
+ }
3728
+ if (challenge.consumed_at !== null) {
3729
+ const consumed = Date.parse(challenge.consumed_at);
3730
+ if (consumed < issued || consumed > Date.parse(challenge.expires_at)) {
3731
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["consumed_at"], message: "challenge consumption must occur before expiry" });
3732
+ }
3733
+ }
3734
+ });
3735
+ CatalogIdentityVerificationResultSchema = z5.object({
3736
+ id: IdSchema,
3737
+ identity_verification_request_id: IdSchema,
3738
+ challenge_id: IdSchema,
3739
+ result_kind: z5.enum(["identity_match", "liveness", "domain_control", "publishing_account_control"]),
3740
+ outcome: z5.enum(["match", "mismatch", "inconclusive"]),
3741
+ private_attestation_reference: z5.string().regex(/^private:\/\/[^\s]+$/).max(2e3),
3742
+ attestation_sha256: Sha256Schema2,
3743
+ recorded_by: IdSchema,
3744
+ recorded_at: IsoDateTimeSchema2
2739
3745
  }).strict();
3746
+ CatalogPrivateEvidenceRetentionEventSchema = z5.object({
3747
+ id: IdSchema,
3748
+ evidence_table: z5.enum(["catalog_profile_claim_evidence_references", "catalog_identity_evidence_references"]),
3749
+ evidence_id: IdSchema,
3750
+ lifecycle_table: z5.enum(["catalog_profile_claim_request_events", "catalog_identity_verification_request_events", "catalog_profile_control_events", "catalog_identity_verification_record_events"]),
3751
+ lifecycle_event_id: IdSchema,
3752
+ retention_policy: z5.enum(["malformed_7d", "sensitive_30d", "workflow_24m"]),
3753
+ purge_after: IsoDateTimeSchema2,
3754
+ prior_event_id: IdSchema.nullable(),
3755
+ occurred_at: IsoDateTimeSchema2,
3756
+ created_at: IsoDateTimeSchema2
3757
+ }).strict();
3758
+ CatalogPrivateEvidenceLegalHoldEventSchema = z5.object({
3759
+ id: IdSchema,
3760
+ evidence_table: z5.enum(["catalog_profile_claim_evidence_references", "catalog_identity_evidence_references"]),
3761
+ evidence_id: IdSchema,
3762
+ action: z5.enum(["placed", "released"]),
3763
+ prior_event_id: IdSchema.nullable(),
3764
+ actor_id: IdSchema,
3765
+ reviewer_id: IdSchema,
3766
+ reason: z5.string().trim().min(1).max(2e3),
3767
+ occurred_at: IsoDateTimeSchema2,
3768
+ created_at: IsoDateTimeSchema2
3769
+ }).strict().superRefine((event, context) => {
3770
+ if (event.actor_id === event.reviewer_id) {
3771
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["reviewer_id"], message: "legal hold review must be independent" });
3772
+ }
3773
+ if (event.action === "placed" !== (event.prior_event_id === null)) {
3774
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["prior_event_id"], message: "hold placement is the root and release is its successor" });
3775
+ }
3776
+ });
3777
+ CatalogPrivateEvidenceDeletionReceiptSchema = z5.object({
3778
+ id: IdSchema,
3779
+ evidence_table: z5.enum(["catalog_profile_claim_evidence_references", "catalog_identity_evidence_references"]),
3780
+ evidence_id: IdSchema,
3781
+ claim_token: IdSchema,
3782
+ private_reference_sha256: Sha256Schema2,
3783
+ storage_receipt_reference: z5.string().regex(/^storage:\/\/[^\s]+$/).max(2e3),
3784
+ storage_receipt_sha256: Sha256Schema2,
3785
+ acknowledged_by: IdSchema,
3786
+ storage_deleted_at: IsoDateTimeSchema2,
3787
+ created_at: IsoDateTimeSchema2
3788
+ }).strict();
3789
+ CatalogIdentityVerificationRecordSchema = z5.object({
3790
+ id: IdSchema,
3791
+ identity_verification_request_id: IdSchema,
3792
+ profile_id: IdSchema,
3793
+ profile_control_id: IdSchema,
3794
+ subject_kind: z5.enum(["person", "publisher"]),
3795
+ method_version_id: IdSchema,
3796
+ derived_evidence_sha256: Sha256Schema2,
3797
+ current_state: CatalogIdentityVerificationRecordStateSchema,
3798
+ created_at: IsoDateTimeSchema2,
3799
+ terminal_at: IsoDateTimeSchema2.nullable()
3800
+ }).strict().superRefine((record, context) => {
3801
+ const terminal = ["revoked", "expired"].includes(record.current_state);
3802
+ if (terminal !== (record.terminal_at !== null)) {
3803
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["terminal_at"], message: "terminal_at must match terminal Identity Record state" });
3804
+ }
3805
+ });
3806
+ CatalogIdentityVerificationRecordEventSchema = z5.object({
3807
+ id: IdSchema,
3808
+ identity_verification_record_id: IdSchema,
3809
+ state: CatalogIdentityVerificationRecordStateSchema,
3810
+ prior_event_id: IdSchema.nullable(),
3811
+ actor_id: IdSchema,
3812
+ reviewer_id: IdSchema.nullable(),
3813
+ reason: z5.string().trim().min(1).max(2e3).nullable(),
3814
+ occurred_at: IsoDateTimeSchema2,
3815
+ created_at: IsoDateTimeSchema2
3816
+ }).strict().superRefine((event, context) => {
3817
+ if (event.state === "active" !== (event.prior_event_id === null)) {
3818
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["prior_event_id"], message: "only the initial active state is a root event" });
3819
+ }
3820
+ if (event.state !== "active" && event.reason === null) {
3821
+ context.addIssue({ code: z5.ZodIssueCode.custom, path: ["reason"], message: `${event.state} requires a reason` });
3822
+ }
3823
+ });
2740
3824
  }
2741
3825
  });
2742
3826
 
@@ -2751,6 +3835,8 @@ var init_src = __esm({
2751
3835
  init_install_targets();
2752
3836
  init_security_scan();
2753
3837
  init_skill_package();
3838
+ init_catalog();
3839
+ init_catalog_trust();
2754
3840
  init_contract();
2755
3841
  }
2756
3842
  });
@@ -3070,8 +4156,8 @@ import { mkdir as mkdir2, readFile as readFile3, writeFile, chmod } from "node:f
3070
4156
 
3071
4157
  // src/lib/invocation.ts
3072
4158
  var NPX_HINTS = ["_npx", "npm-cache/_npx", "npm-cache\\_npx", ".npm/_npx"];
3073
- var NPX_INVOCATION = "npx -y @floomhq/floom";
3074
- var GLOBAL_INVOCATION = "floom";
4159
+ var NPX_INVOCATION = "npx -y @floomhq/skills";
4160
+ var GLOBAL_INVOCATION = "floom-skills";
3075
4161
  var cached = null;
3076
4162
  function detect() {
3077
4163
  const override = process.env.FLOOM_INVOKED_AS;
@@ -3089,16 +4175,16 @@ function cliInvocation() {
3089
4175
  return cached;
3090
4176
  }
3091
4177
  function cliCmd(cmd) {
3092
- const stripped = cmd.startsWith("floom ") ? cmd.slice("floom ".length) : cmd;
4178
+ const stripped = cmd.startsWith("floom-skills ") ? cmd.slice("floom-skills ".length) : cmd.startsWith("floom ") ? cmd.slice("floom ".length) : cmd;
3093
4179
  return `${cliInvocation()} ${stripped}`;
3094
4180
  }
3095
4181
 
3096
4182
  // src/config.ts
3097
4183
  var CONFIG_DIR = join3(homedir2(), ".floom");
3098
4184
  var AUTH_FILE = join3(CONFIG_DIR, "auth.json");
3099
- var DEFAULT_APP_URL = "https://floom.dev";
3100
- var DEFAULT_API_URL = "https://floom.dev/api/v1";
3101
- var TRUSTED_API_HOSTS = /* @__PURE__ */ new Set(["floom.dev", "try.floom.dev"]);
4185
+ var DEFAULT_APP_URL = "https://skills.floom.dev";
4186
+ var DEFAULT_API_URL = "https://skills.floom.dev/api/v1";
4187
+ var TRUSTED_API_HOSTS = /* @__PURE__ */ new Set(["skills.floom.dev"]);
3102
4188
  var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1"]);
3103
4189
  function devModeEnabled() {
3104
4190
  const v = process.env.FLOOM_DEV;
@@ -3112,7 +4198,7 @@ function isTrustedApiUrl(apiUrl) {
3112
4198
  return url.protocol === "https:";
3113
4199
  }
3114
4200
  if (LOOPBACK_HOSTS.has(url.hostname) && devModeEnabled()) {
3115
- return true;
4201
+ return url.protocol === "http:" || url.protocol === "https:";
3116
4202
  }
3117
4203
  return false;
3118
4204
  } catch {
@@ -3149,13 +4235,13 @@ async function readRawAuth() {
3149
4235
  `Cannot read your Floom auth file (permission denied).
3150
4236
  Fix: chmod 600 ~/.floom/auth.json
3151
4237
  Or re-authenticate: ${cliCmd("login")}
3152
- More help: https://floom.dev/docs#troubleshooting`
4238
+ More help: https://skills.floom.dev/docs#troubleshooting`
3153
4239
  );
3154
4240
  }
3155
4241
  throw new Error(
3156
4242
  `Cannot read your Floom auth file.
3157
4243
  Run: ${cliCmd("login")}
3158
- More help: https://floom.dev/docs#troubleshooting`
4244
+ More help: https://skills.floom.dev/docs#troubleshooting`
3159
4245
  );
3160
4246
  }
3161
4247
  try {
@@ -3164,7 +4250,7 @@ async function readRawAuth() {
3164
4250
  throw new Error(
3165
4251
  `Your Floom auth file is corrupted.
3166
4252
  Run: ${cliCmd("login")} to generate a fresh one.
3167
- More help: https://floom.dev/docs#troubleshooting`
4253
+ More help: https://skills.floom.dev/docs#troubleshooting`
3168
4254
  );
3169
4255
  }
3170
4256
  }
@@ -3193,7 +4279,11 @@ function getApiUrl() {
3193
4279
  return DEFAULT_API_URL;
3194
4280
  }
3195
4281
  function getAppUrl() {
3196
- return process.env.FLOOM_APP_URL ?? DEFAULT_APP_URL;
4282
+ const configured = process.env.FLOOM_APP_URL?.trim();
4283
+ if (!configured) return DEFAULT_APP_URL;
4284
+ const normalized = trustedApiUrlOrDefault(`${configured.replace(/\/$/, "")}/api/v1`);
4285
+ if (normalized === DEFAULT_API_URL) return DEFAULT_APP_URL;
4286
+ return normalized.replace(/\/api\/v1$/, "");
3197
4287
  }
3198
4288
  function getApiBaseUrls(preferred) {
3199
4289
  const explicitApiUrl = process.env.FLOOM_API_URL?.trim();
@@ -3287,7 +4377,7 @@ async function getMachineIdentity() {
3287
4377
  }
3288
4378
 
3289
4379
  // src/version.ts
3290
- var VERSION = "1.0.2";
4380
+ var VERSION = "1.1.0";
3291
4381
 
3292
4382
  // src/api-client.ts
3293
4383
  var DEFAULT_TIMEOUT_MS = 2e4;
@@ -3334,7 +4424,7 @@ async function readLimitedText(res, limitBytes = MAX_ERROR_BODY_BYTES) {
3334
4424
  return truncated ? `${text}
3335
4425
  [truncated]` : text;
3336
4426
  }
3337
- var HELP = "https://floom.dev/docs#troubleshooting";
4427
+ var HELP = "https://skills.floom.dev/docs#troubleshooting";
3338
4428
  function friendlyApiErrorMessage(code, raw, status) {
3339
4429
  if (code === "AUTH_REQUIRED" || code === "TOKEN_INVALID" || status === 401) {
3340
4430
  return `Not signed in.
@@ -3361,7 +4451,7 @@ function friendlyApiErrorMessage(code, raw, status) {
3361
4451
  }
3362
4452
  if (code === "CLI_VERSION_TOO_OLD") {
3363
4453
  return `Your CLI is out of date.
3364
- Run: npm i -g @floomhq/floom@latest
4454
+ Run: npm i -g @floomhq/skills@latest
3365
4455
  More help: ${HELP}`;
3366
4456
  }
3367
4457
  if (code === "FILE_TOO_LARGE" || code === "BUNDLE_TOO_LARGE") {
@@ -3382,7 +4472,7 @@ async function api(path, opts = {}) {
3382
4472
  "AUTH_REQUIRED",
3383
4473
  `Not signed in.
3384
4474
  Run: ${cliCmd("login")}
3385
- More help: https://floom.dev/docs#troubleshooting`
4475
+ More help: https://skills.floom.dev/docs#troubleshooting`
3386
4476
  );
3387
4477
  }
3388
4478
  let lastError = null;
@@ -3416,9 +4506,9 @@ async function api(path, opts = {}) {
3416
4506
  } catch (e) {
3417
4507
  lastError = new FloomError(
3418
4508
  "INTERNAL_ERROR",
3419
- `Cannot reach Floom (${base}): ${e.message}
4509
+ `Cannot reach Floom Skills (${base}): ${e.message}
3420
4510
  Check your internet connection or firewall. If on a corporate network, you may need to set a proxy: npm config set proxy http://...
3421
- More help: https://floom.dev/docs#troubleshooting`,
4511
+ More help: https://skills.floom.dev/docs#troubleshooting`,
3422
4512
  { apiUrl: base }
3423
4513
  );
3424
4514
  continue;
@@ -3606,7 +4696,7 @@ Fix: replace the link with the real file contents:
3606
4696
 
3607
4697
  (or move the target file under the skill folder if it lives elsewhere)
3608
4698
 
3609
- More help: https://floom.dev/docs#skill-folder-rules`
4699
+ More help: https://skills.floom.dev/docs#skill-folder-rules`
3610
4700
  );
3611
4701
  }
3612
4702
  if (entry.isDirectory()) {
@@ -3772,7 +4862,7 @@ async function loginCommand() {
3772
4862
  ]);
3773
4863
  if (cliCmd("login").startsWith("npx ")) {
3774
4864
  log.blank();
3775
- log.info(" Tip: install once with npm i -g @floomhq/floom and just type `floom` after that.");
4865
+ log.info(" Tip: install once with npm i -g @floomhq/skills and just type `floom-skills` after that.");
3776
4866
  }
3777
4867
  return;
3778
4868
  }
@@ -3793,7 +4883,7 @@ async function loginCommand() {
3793
4883
  log.err("Login timed out \u2014 the browser window expired.");
3794
4884
  printNext([
3795
4885
  { command: cliCmd("login"), description: "try again" },
3796
- { command: "More help: https://floom.dev/docs#troubleshooting" }
4886
+ { command: "More help: https://skills.floom.dev/docs#troubleshooting" }
3797
4887
  ]);
3798
4888
  process.exitCode = 1;
3799
4889
  }
@@ -3817,7 +4907,7 @@ async function logoutCommand(opts = {}, deps = {}) {
3817
4907
  remoteRevokeFailed = true;
3818
4908
  process.exitCode = 1;
3819
4909
  log.err(
3820
- "Local session cleared. Other devices are still authenticated.\nSign in at https://floom.dev/settings to revoke other sessions from the web."
4910
+ "Local session cleared. Other devices are still authenticated.\nSign in at https://skills.floom.dev/settings to revoke other sessions from the web."
3821
4911
  );
3822
4912
  } else {
3823
4913
  log.warn(`Remote session revoke failed: ${error.message}`);
@@ -3940,7 +5030,7 @@ async function accountCommand(opts = {}) {
3940
5030
  init_src();
3941
5031
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3942
5032
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3943
- import { z as z3 } from "zod";
5033
+ import { z as z6 } from "zod";
3944
5034
 
3945
5035
  // src/commands/sync-engine.ts
3946
5036
  init_src();
@@ -4011,9 +5101,9 @@ async function readManifest(root) {
4011
5101
  if (err.code === "ENOENT") return null;
4012
5102
  if (error instanceof SyntaxError || error instanceof ZodError) {
4013
5103
  throw new Error(
4014
- `Corrupted manifest at ${manifestPath(root)}. Remove that file or run floom pull after backing up local edits.
4015
- Run: rm ${manifestPath(root)} && npx -y @floomhq/floom pull
4016
- More help: https://floom.dev/docs#troubleshooting`
5104
+ `Corrupted manifest at ${manifestPath(root)}. Remove that file or run floom-skills pull after backing up local edits.
5105
+ Run: rm ${manifestPath(root)} && npx -y @floomhq/skills pull
5106
+ More help: https://skills.floom.dev/docs#troubleshooting`
4017
5107
  );
4018
5108
  }
4019
5109
  throw error;
@@ -4476,7 +5566,7 @@ function createMcpServer(deps = {}) {
4476
5566
  {
4477
5567
  title: "Floom Search Skills",
4478
5568
  description: "Search the authenticated workspace skill library by keyword. Returns matching skills with title and description.",
4479
- inputSchema: { query: z3.string().describe("Search query string") },
5569
+ inputSchema: { query: z6.string().describe("Search query string") },
4480
5570
  annotations: {
4481
5571
  readOnlyHint: true,
4482
5572
  destructiveHint: false,
@@ -4502,7 +5592,7 @@ function createMcpServer(deps = {}) {
4502
5592
  query,
4503
5593
  status: "error",
4504
5594
  message: err.message,
4505
- hint: "Run: npx -y @floomhq/floom login"
5595
+ hint: "Run: npx -y @floomhq/skills login"
4506
5596
  });
4507
5597
  }
4508
5598
  }
@@ -4512,7 +5602,7 @@ function createMcpServer(deps = {}) {
4512
5602
  {
4513
5603
  title: "Floom Get Skill",
4514
5604
  description: "Fetch full skill detail (body, files, version history) for a given skill slug from the workspace.",
4515
- inputSchema: { slug: z3.string().describe("Skill slug, e.g. 'brand-voice'") },
5605
+ inputSchema: { slug: z6.string().describe("Skill slug, e.g. 'brand-voice'") },
4516
5606
  annotations: {
4517
5607
  readOnlyHint: true,
4518
5608
  destructiveHint: false,
@@ -4538,7 +5628,7 @@ function createMcpServer(deps = {}) {
4538
5628
  slug,
4539
5629
  status: "error",
4540
5630
  message: err.message,
4541
- hint: "Run: npx -y @floomhq/floom login"
5631
+ hint: "Run: npx -y @floomhq/skills login"
4542
5632
  });
4543
5633
  }
4544
5634
  }
@@ -4549,8 +5639,8 @@ function createMcpServer(deps = {}) {
4549
5639
  title: "Floom Send Feedback",
4550
5640
  description: "Send feedback, a feature request, or a bug report to the Floom team.",
4551
5641
  inputSchema: {
4552
- message: z3.string().describe("Feedback message"),
4553
- type: z3.enum(["feedback", "bug", "feature"]).default("feedback").describe("Type of feedback")
5642
+ message: z6.string().describe("Feedback message"),
5643
+ type: z6.enum(["feedback", "bug", "feature"]).default("feedback").describe("Type of feedback")
4554
5644
  },
4555
5645
  annotations: {
4556
5646
  readOnlyHint: false,
@@ -4590,10 +5680,10 @@ async function mcpCommand() {
4590
5680
  This command is launched by your AI agent, not run directly.
4591
5681
 
4592
5682
  Add this to your agent's MCP configuration:
4593
- {"command":"npx","args":["-y","@floomhq/floom","mcp"]}
5683
+ {"command":"npx","args":["-y","@floomhq/skills","mcp"]}
4594
5684
 
4595
5685
  Claude Code users can instead run:
4596
- claude mcp add floom -- npx -y @floomhq/floom mcp
5686
+ claude mcp add floom -- npx -y @floomhq/skills mcp
4597
5687
 
4598
5688
  Press Ctrl+C to stop.
4599
5689
  `
@@ -5004,7 +6094,7 @@ async function pushExplicitPath(pathArg, options, pushApi, authed) {
5004
6094
  if (!await hasSkillMd(folder)) {
5005
6095
  if (!json) {
5006
6096
  log.err(`No SKILL.md at the root of ${pathArg}.`);
5007
- log.info(" Every skill folder needs a SKILL.md at its root. See: https://floom.dev/docs#concept");
6097
+ log.info(" Every skill folder needs a SKILL.md at its root. See: https://skills.floom.dev/docs#concept");
5008
6098
  }
5009
6099
  process.exitCode = 2;
5010
6100
  return;
@@ -5486,7 +6576,7 @@ async function pullCommand(skillArg, rawOpts = {}) {
5486
6576
  log.blank();
5487
6577
  log.info(`Or use: ${cliCmd("pull --agent claude")}`);
5488
6578
  log.blank();
5489
- log.info("More help: https://floom.dev/docs#agents");
6579
+ log.info("More help: https://skills.floom.dev/docs#agents");
5490
6580
  }
5491
6581
  process.exitCode = 1;
5492
6582
  return;
@@ -5817,7 +6907,7 @@ function printPreview(plan) {
5817
6907
  log.err(` Keep your local version: ${cliCmd(`push <${skill.slug}-dir>`)}`);
5818
6908
  }
5819
6909
  log.err("Your local copy is always backed up to .floom/backups/ first.");
5820
- log.err("More: https://floom.dev/docs#conflicts");
6910
+ log.err("More: https://skills.floom.dev/docs#conflicts");
5821
6911
  }
5822
6912
  }
5823
6913
  async function defaultConfirmProceed() {
@@ -6042,7 +7132,7 @@ async function syncCommand(rawOpts = {}, deps = {}) {
6042
7132
  } else {
6043
7133
  log.err("No agents detected \u2014 install Claude, Codex, Cursor, Gemini, or OpenCode, then re-run.");
6044
7134
  log.info("Floom syncs into one of: Claude, Codex, Cursor, Gemini, OpenCode.");
6045
- log.info("More: https://floom.dev/docs#agents");
7135
+ log.info("More: https://skills.floom.dev/docs#agents");
6046
7136
  }
6047
7137
  process.exitCode = 1;
6048
7138
  return;
@@ -6329,7 +7419,7 @@ async function statusCommand(rawOpts = {}) {
6329
7419
  log.info("If someone sent you a shared skill:");
6330
7420
  log.command(cliCmd("install <link>"));
6331
7421
  log.blank();
6332
- log.info("More help: https://floom.dev/docs#agents");
7422
+ log.info("More help: https://skills.floom.dev/docs#agents");
6333
7423
  }
6334
7424
  process.exitCode = 1;
6335
7425
  return;
@@ -6619,19 +7709,28 @@ init_prompt();
6619
7709
  var TOKEN_RE = /^fls_[A-Za-z0-9_-]{32,}$/;
6620
7710
  var SAFE_SLUG_RE2 = /^(?=.{1,80}$)[a-z0-9]+(?:-[a-z0-9]+)*$/;
6621
7711
  var MAX_DECODED_FILE_BYTES2 = 2 * 1024 * 1024;
6622
- function parseToken(input) {
7712
+ function trustedCatalogOrigin(url) {
7713
+ if (url.protocol === "https:") return true;
7714
+ const dev = process.env.FLOOM_DEV;
7715
+ const devMode = dev === "1" || dev === "true";
7716
+ return devMode && url.protocol === "http:" && (url.hostname === "127.0.0.1" || url.hostname === "localhost");
7717
+ }
7718
+ function parseInstallSource(input) {
6623
7719
  const trimmed = input.trim();
6624
- if (TOKEN_RE.test(trimmed)) return trimmed;
7720
+ if (TOKEN_RE.test(trimmed)) return { kind: "share", token: trimmed };
7721
+ let url;
6625
7722
  try {
6626
- const url = new URL(trimmed);
6627
- const parts = url.pathname.split("/").filter(Boolean);
6628
- if (parts.length >= 2 && parts[parts.length - 2] === "s") {
6629
- const candidate = parts[parts.length - 1];
6630
- if (candidate && TOKEN_RE.test(candidate)) return candidate;
6631
- }
6632
- const last = parts[parts.length - 1];
6633
- if (last && TOKEN_RE.test(last)) return last;
7723
+ url = new URL(trimmed);
6634
7724
  } catch {
7725
+ return null;
7726
+ }
7727
+ const parts = url.pathname.split("/").filter(Boolean);
7728
+ const last = parts[parts.length - 1];
7729
+ const parent = parts.length >= 2 ? parts[parts.length - 2] : null;
7730
+ if (parent === "s" && last && TOKEN_RE.test(last)) return { kind: "share", token: last };
7731
+ if (last && TOKEN_RE.test(last)) return { kind: "share", token: last };
7732
+ if (parent === "skills" && last && SAFE_SLUG_RE2.test(last) && trustedCatalogOrigin(url)) {
7733
+ return { kind: "catalog", origin: url.origin, slug: last };
6635
7734
  }
6636
7735
  return null;
6637
7736
  }
@@ -6666,9 +7765,9 @@ function bytesForShareFile(file) {
6666
7765
  function derivedSlug(title) {
6667
7766
  return title.toLowerCase().replace(/[^a-z0-9 -]/g, "").trim().replace(/\s+/g, "-").replace(/-+/g, "-").slice(0, 80).replace(/^-+|-+$/g, "") || "shared-skill";
6668
7767
  }
6669
- async function fetchPublicShare(token) {
6670
- const apiBase = getAppUrl().replace(/\/$/, "");
6671
- const url = `${apiBase}/api/v1/share/${encodeURIComponent(token)}`;
7768
+ async function fetchInstallSource(source) {
7769
+ const url = source.kind === "share" ? `${getAppUrl().replace(/\/$/, "")}/api/v1/share/${encodeURIComponent(source.token)}` : `${source.origin}/api/v1/catalog/install/skills/${encodeURIComponent(source.slug)}`;
7770
+ const notFoundMessage = source.kind === "share" ? "Share link not found or has been revoked." : "Install link not found or has been withdrawn.";
6672
7771
  const controller = new AbortController();
6673
7772
  const timer = setTimeout(() => controller.abort(), 3e4);
6674
7773
  let res;
@@ -6681,7 +7780,7 @@ async function fetchPublicShare(token) {
6681
7780
  clearTimeout(timer);
6682
7781
  }
6683
7782
  if (res.status === 404) {
6684
- throw new FloomError("SKILL_NOT_FOUND", "Share link not found or has been revoked.");
7783
+ throw new FloomError("SKILL_NOT_FOUND", notFoundMessage);
6685
7784
  }
6686
7785
  if (!res.ok) throw new Error(`Floom API returned HTTP ${res.status}. Try again in a moment.`);
6687
7786
  let json;
@@ -6763,17 +7862,18 @@ async function installCommand(input, rawOpts = {}) {
6763
7862
  throw error;
6764
7863
  }
6765
7864
  const json = flags.json;
6766
- const token = parseToken(input);
6767
- if (!token) {
7865
+ const source = parseInstallSource(input);
7866
+ if (!source) {
6768
7867
  if (!json) {
6769
- log.err("That doesn't look like a Floom share link. It should look like: https://floom.dev/s/fls_xxx");
7868
+ log.err("That doesn't look like a Floom share link. It must look like: https://skills.floom.dev/s/fls_xxx");
7869
+ log.info("A public catalog Skill page also works: https://<catalog host>/skills/<slug>");
6770
7870
  }
6771
7871
  process.exitCode = 2;
6772
7872
  return;
6773
7873
  }
6774
7874
  let shareData;
6775
7875
  try {
6776
- shareData = await fetchPublicShare(token);
7876
+ shareData = await fetchInstallSource(source);
6777
7877
  } catch (e) {
6778
7878
  if (!json) {
6779
7879
  log.err(e instanceof FloomError ? e.message : e.message);
@@ -6798,7 +7898,7 @@ async function installCommand(input, rawOpts = {}) {
6798
7898
  log.info("Floom can install shared skills into Claude, Codex, Cursor, Gemini, or OpenCode.");
6799
7899
  log.info("Install one of those agents, then run this command again.");
6800
7900
  log.blank();
6801
- log.info("More help: https://floom.dev/docs#agents");
7901
+ log.info("More help: https://skills.floom.dev/docs#agents");
6802
7902
  }
6803
7903
  process.exitCode = 1;
6804
7904
  return;
@@ -7005,7 +8105,7 @@ description: TODO: Use when the user needs help with [specific task, workflow, o
7005
8105
  <!--
7006
8106
  This file teaches your AI agent when and how to use the skill.
7007
8107
  Keep it practical: triggers, rules, examples, and done criteria.
7008
- See: https://floom.dev/docs/skills
8108
+ See: https://skills.floom.dev/docs/skills
7009
8109
  -->
7010
8110
 
7011
8111
  Use this skill when:
@@ -7250,7 +8350,7 @@ function npmLatest() {
7250
8350
  return new Promise((resolveP) => {
7251
8351
  let child;
7252
8352
  try {
7253
- child = spawn3("npm", ["view", "@floomhq/floom", "version"], { stdio: ["ignore", "pipe", "ignore"] });
8353
+ child = spawn3("npm", ["view", "@floomhq/skills", "version"], { stdio: ["ignore", "pipe", "ignore"] });
7254
8354
  } catch {
7255
8355
  resolveP(null);
7256
8356
  return;
@@ -7303,7 +8403,7 @@ async function doctorCommand(opts = {}) {
7303
8403
  }
7304
8404
  }
7305
8405
  if (authOk) {
7306
- checks.push({ name: "api", status: "pass", message: "https://floom.dev reachable", fix: null });
8406
+ checks.push({ name: "api", status: "pass", message: "https://skills.floom.dev reachable", fix: null });
7307
8407
  } else {
7308
8408
  checks.push({ name: "api", status: "warn", message: "skipped \u2014 sign in first", fix: cliCmd("login") });
7309
8409
  }
@@ -7370,11 +8470,11 @@ async function doctorCommand(opts = {}) {
7370
8470
  }
7371
8471
  const latest = await npmLatest();
7372
8472
  if (!latest) {
7373
- checks.push({ name: "version", status: "warn", message: `@floomhq/floom ${VERSION}; latest version unreachable`, fix: null });
8473
+ checks.push({ name: "version", status: "warn", message: `@floomhq/skills ${VERSION}; latest version unreachable`, fix: null });
7374
8474
  } else if (significantlyOutdated(VERSION, latest)) {
7375
- checks.push({ name: "version", status: "warn", message: `@floomhq/floom ${VERSION} installed, latest is ${latest}`, fix: "npx -y @floomhq/floom@latest" });
8475
+ checks.push({ name: "version", status: "warn", message: `@floomhq/skills ${VERSION} installed, latest is ${latest}`, fix: "npx -y @floomhq/skills@latest" });
7376
8476
  } else {
7377
- checks.push({ name: "version", status: "pass", message: `@floomhq/floom ${VERSION} is current`, fix: null });
8477
+ checks.push({ name: "version", status: "pass", message: `@floomhq/skills ${VERSION} is current`, fix: null });
7378
8478
  }
7379
8479
  const failures = checks.filter((c) => c.status === "fail");
7380
8480
  const warnings = checks.filter((c) => c.status === "warn");
@@ -8119,8 +9219,8 @@ var COMMON_FLAGS = `Common flags
8119
9219
  --no-secret-check with push, skip the pre-publish secret scan`;
8120
9220
  function printGroupedHelp() {
8121
9221
  const out2 = process.stdout;
8122
- out2.write("\n" + chalk7.bold("Usage: floom [command]") + "\n\n");
8123
- out2.write(` ${chalk7.cyan.bold("floom")} your dashboard \u2014 Library and agent status at a glance
9222
+ out2.write("\n" + chalk7.bold("Usage: floom-skills [command]") + "\n\n");
9223
+ out2.write(` ${chalk7.cyan.bold("floom-skills")} your dashboard \u2014 Library and agent status at a glance
8124
9224
  `);
8125
9225
  const allNames = GROUPS.flatMap((g) => g.rows.map((r) => r.name));
8126
9226
  const width = Math.max(...allNames.map((n) => n.length), 14);
@@ -8133,7 +9233,7 @@ function printGroupedHelp() {
8133
9233
  }
8134
9234
  }
8135
9235
  out2.write("\n" + COMMON_FLAGS + "\n");
8136
- out2.write("\n" + chalk7.dim("More help: https://floom.dev/docs") + "\n");
9236
+ out2.write("\n" + chalk7.dim("More help: https://skills.floom.dev/docs") + "\n");
8137
9237
  }
8138
9238
 
8139
9239
  // src/index.ts
@@ -8144,7 +9244,7 @@ function aliasNotice(oldName, newName) {
8144
9244
  log.notice(`"${oldName}" is now "${newName}" \u2014 both work for now.`);
8145
9245
  }
8146
9246
  var program = new Command();
8147
- program.name("floom").description("Floom: one shared skill library, synced across every AI agent.").version(VERSION).addHelpCommand(false).helpOption("-h, --help", "show grouped help").allowExcessArguments(true).showSuggestionAfterError(true).showHelpAfterError(false);
9247
+ program.name("floom-skills").description("Floom Skills: publish, install, sync, and share AI agent skills.").version(VERSION).addHelpCommand(false).helpOption("-h, --help", "show grouped help").allowExcessArguments(true).showSuggestionAfterError(true).showHelpAfterError(false);
8148
9248
  program.helpInformation = function helpInformation() {
8149
9249
  printGroupedHelp();
8150
9250
  return "";
@@ -8159,8 +9259,8 @@ program.action(async (_opts, cmd) => {
8159
9259
  log.err(`unknown command: ${unknown}`);
8160
9260
  const knownNames = program.commands.map((c) => c.name());
8161
9261
  const suggestion = closestCommand(unknown, knownNames);
8162
- if (suggestion) log.info(`Did you mean: floom ${suggestion}?`);
8163
- log.info("Run: floom --help");
9262
+ if (suggestion) log.info(`Did you mean: floom-skills ${suggestion}?`);
9263
+ log.info("Run: floom-skills --help");
8164
9264
  process.exitCode = 2;
8165
9265
  return;
8166
9266
  }