@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/README.md +34 -40
- package/dist/index.js +1364 -264
- package/dist/version.js +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2352,12 +2352,170 @@ var init_skill_package = __esm({
|
|
|
2352
2352
|
}
|
|
2353
2353
|
});
|
|
2354
2354
|
|
|
2355
|
-
// ../shared/src/contract/
|
|
2355
|
+
// ../shared/src/contract/catalog-install.ts
|
|
2356
2356
|
import { z as z2 } from "zod";
|
|
2357
|
-
var
|
|
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 =
|
|
2386
|
-
RequestIdSchema =
|
|
2387
|
-
|
|
2388
|
-
IdSchema =
|
|
2389
|
-
SlugSchema =
|
|
2390
|
-
EmailSchema =
|
|
2391
|
-
|
|
2392
|
-
VersionSeqSchema =
|
|
2393
|
-
UrlSchema =
|
|
2394
|
-
ErrorDetailSchema =
|
|
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:
|
|
2555
|
+
message: z3.string().min(1),
|
|
2397
2556
|
request_id: RequestIdSchema
|
|
2398
|
-
}).catchall(
|
|
2399
|
-
ErrorEnvelopeSchema =
|
|
2557
|
+
}).catchall(z3.unknown());
|
|
2558
|
+
ErrorEnvelopeSchema = z3.object({
|
|
2400
2559
|
error: ErrorDetailSchema
|
|
2401
2560
|
}).strict();
|
|
2402
|
-
UserSchema =
|
|
2561
|
+
UserSchema = z3.object({
|
|
2403
2562
|
id: IdSchema,
|
|
2404
2563
|
email: EmailSchema,
|
|
2405
|
-
name:
|
|
2564
|
+
name: z3.string().min(1),
|
|
2406
2565
|
avatar_url: UrlSchema.nullable()
|
|
2407
2566
|
}).strict();
|
|
2408
|
-
WorkspaceSchema =
|
|
2567
|
+
WorkspaceSchema = z3.object({
|
|
2409
2568
|
id: IdSchema,
|
|
2410
2569
|
slug: SlugSchema,
|
|
2411
|
-
name:
|
|
2570
|
+
name: z3.string().min(1).max(120)
|
|
2412
2571
|
}).strict();
|
|
2413
|
-
MeResponseSchema =
|
|
2572
|
+
MeResponseSchema = z3.object({
|
|
2414
2573
|
user: UserSchema,
|
|
2415
2574
|
workspace: WorkspaceSchema.nullable()
|
|
2416
2575
|
}).strict();
|
|
2417
|
-
WorkspaceCreateRequestSchema =
|
|
2418
|
-
name:
|
|
2576
|
+
WorkspaceCreateRequestSchema = z3.object({
|
|
2577
|
+
name: z3.string().trim().min(1).max(120)
|
|
2419
2578
|
}).strict();
|
|
2420
|
-
WorkspaceCreateResponseSchema =
|
|
2579
|
+
WorkspaceCreateResponseSchema = z3.object({
|
|
2421
2580
|
workspace: WorkspaceSchema
|
|
2422
2581
|
}).strict();
|
|
2423
|
-
MemberSchema =
|
|
2424
|
-
name:
|
|
2582
|
+
MemberSchema = z3.object({
|
|
2583
|
+
name: z3.string().min(1),
|
|
2425
2584
|
email: EmailSchema,
|
|
2426
|
-
joined_at:
|
|
2585
|
+
joined_at: IsoDateTimeSchema2
|
|
2427
2586
|
}).strict();
|
|
2428
|
-
MembersListResponseSchema =
|
|
2587
|
+
MembersListResponseSchema = z3.object({
|
|
2429
2588
|
workspace: WorkspaceSchema,
|
|
2430
|
-
members:
|
|
2431
|
-
total:
|
|
2589
|
+
members: z3.array(MemberSchema),
|
|
2590
|
+
total: z3.number().int().nonnegative()
|
|
2432
2591
|
}).strict();
|
|
2433
|
-
InviteStatusSchema =
|
|
2592
|
+
InviteStatusSchema = z3.enum([
|
|
2434
2593
|
"pending",
|
|
2435
2594
|
"accepted",
|
|
2436
2595
|
"revoked",
|
|
2437
2596
|
"expired"
|
|
2438
2597
|
]);
|
|
2439
|
-
InviteCreateRequestSchema =
|
|
2598
|
+
InviteCreateRequestSchema = z3.object({
|
|
2440
2599
|
email: EmailSchema
|
|
2441
2600
|
}).strict();
|
|
2442
|
-
InviteSchema =
|
|
2601
|
+
InviteSchema = z3.object({
|
|
2443
2602
|
email: EmailSchema,
|
|
2444
2603
|
status: InviteStatusSchema,
|
|
2445
|
-
expires_at:
|
|
2446
|
-
created_at:
|
|
2604
|
+
expires_at: IsoDateTimeSchema2,
|
|
2605
|
+
created_at: IsoDateTimeSchema2
|
|
2447
2606
|
}).strict();
|
|
2448
|
-
InviteCreateResponseSchema =
|
|
2607
|
+
InviteCreateResponseSchema = z3.object({
|
|
2449
2608
|
invite: InviteSchema,
|
|
2450
2609
|
accept_url: UrlSchema
|
|
2451
2610
|
}).strict();
|
|
2452
|
-
InviteLinkRotateResponseSchema =
|
|
2611
|
+
InviteLinkRotateResponseSchema = z3.object({
|
|
2453
2612
|
invite: InviteSchema,
|
|
2454
2613
|
accept_url: UrlSchema
|
|
2455
2614
|
}).strict();
|
|
2456
|
-
InvitesListResponseSchema =
|
|
2457
|
-
invites:
|
|
2458
|
-
total:
|
|
2615
|
+
InvitesListResponseSchema = z3.object({
|
|
2616
|
+
invites: z3.array(InviteSchema),
|
|
2617
|
+
total: z3.number().int().nonnegative()
|
|
2459
2618
|
}).strict();
|
|
2460
|
-
InviteAcceptResponseSchema =
|
|
2619
|
+
InviteAcceptResponseSchema = z3.object({
|
|
2461
2620
|
invite: InviteSchema.extend({
|
|
2462
|
-
status:
|
|
2463
|
-
accepted_at:
|
|
2621
|
+
status: z3.literal("accepted"),
|
|
2622
|
+
accepted_at: IsoDateTimeSchema2
|
|
2464
2623
|
}),
|
|
2465
2624
|
workspace: WorkspaceSchema
|
|
2466
2625
|
}).strict();
|
|
2467
|
-
TargetSchema =
|
|
2626
|
+
TargetSchema = z3.enum([
|
|
2468
2627
|
"claude",
|
|
2469
2628
|
"codex",
|
|
2470
2629
|
"cursor",
|
|
2471
2630
|
"gemini",
|
|
2472
2631
|
"opencode"
|
|
2473
2632
|
]);
|
|
2474
|
-
VersionRefSchema =
|
|
2633
|
+
VersionRefSchema = z3.object({
|
|
2475
2634
|
version_seq: VersionSeqSchema,
|
|
2476
|
-
display:
|
|
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:
|
|
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 =
|
|
2487
|
-
name:
|
|
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 =
|
|
2493
|
-
path:
|
|
2494
|
-
size_bytes:
|
|
2495
|
-
size:
|
|
2496
|
-
sha256:
|
|
2497
|
-
mime:
|
|
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 =
|
|
2500
|
-
path:
|
|
2501
|
-
kind:
|
|
2502
|
-
parent_path:
|
|
2503
|
-
depth:
|
|
2504
|
-
size_bytes:
|
|
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 =
|
|
2507
|
-
available:
|
|
2665
|
+
FileDownloadSchema = z3.object({
|
|
2666
|
+
available: z3.boolean(),
|
|
2508
2667
|
url: UrlSchema.nullable(),
|
|
2509
|
-
filename:
|
|
2510
|
-
expires_at:
|
|
2668
|
+
filename: z3.string().min(1).nullable(),
|
|
2669
|
+
expires_at: IsoDateTimeSchema2.nullable()
|
|
2511
2670
|
}).strict();
|
|
2512
|
-
FileCopySchema =
|
|
2513
|
-
available:
|
|
2514
|
-
source:
|
|
2671
|
+
FileCopySchema = z3.object({
|
|
2672
|
+
available: z3.boolean(),
|
|
2673
|
+
source: z3.enum(["content_text", "safe_extraction", "none"])
|
|
2515
2674
|
}).strict();
|
|
2516
|
-
FileActionSchema =
|
|
2675
|
+
FileActionSchema = z3.object({
|
|
2517
2676
|
copy: FileCopySchema,
|
|
2518
2677
|
download: FileDownloadSchema
|
|
2519
2678
|
}).strict();
|
|
2520
2679
|
TextFileContentSchema = FileMetadataSchema.extend({
|
|
2521
|
-
mode:
|
|
2522
|
-
content_text:
|
|
2523
|
-
safe_extraction:
|
|
2524
|
-
binary:
|
|
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 =
|
|
2528
|
-
status:
|
|
2529
|
-
text_preview:
|
|
2530
|
-
reason:
|
|
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 =
|
|
2533
|
-
filename:
|
|
2534
|
-
size_bytes:
|
|
2535
|
-
sha256:
|
|
2536
|
-
mime:
|
|
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:
|
|
2541
|
-
content_text:
|
|
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 =
|
|
2705
|
+
FileContentSchema = z3.discriminatedUnion("mode", [
|
|
2547
2706
|
TextFileContentSchema,
|
|
2548
2707
|
NonTextFileContentSchema
|
|
2549
2708
|
]);
|
|
2550
|
-
SkillsListItemSchema =
|
|
2709
|
+
SkillsListItemSchema = z3.object({
|
|
2551
2710
|
slug: SlugSchema,
|
|
2552
|
-
title:
|
|
2553
|
-
description:
|
|
2554
|
-
icon:
|
|
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:
|
|
2715
|
+
updated_at: IsoDateTimeSchema2,
|
|
2557
2716
|
updated_by: PersonNameSchema
|
|
2558
2717
|
}).strict();
|
|
2559
|
-
SkillsListResponseSchema =
|
|
2560
|
-
skills:
|
|
2561
|
-
total:
|
|
2562
|
-
order:
|
|
2563
|
-
search:
|
|
2564
|
-
mode:
|
|
2565
|
-
server_search:
|
|
2566
|
-
query_param:
|
|
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:
|
|
2727
|
+
pagination: z3.null()
|
|
2569
2728
|
}).strict();
|
|
2570
|
-
VersionHistoryItemSchema =
|
|
2729
|
+
VersionHistoryItemSchema = z3.object({
|
|
2571
2730
|
version_seq: VersionSeqSchema,
|
|
2572
|
-
display:
|
|
2573
|
-
created_at:
|
|
2731
|
+
display: z3.string().regex(/^v[1-9][0-9]*$/),
|
|
2732
|
+
created_at: IsoDateTimeSchema2,
|
|
2574
2733
|
created_by: PersonNameSchema,
|
|
2575
|
-
changelog:
|
|
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:
|
|
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 =
|
|
2586
|
-
skill:
|
|
2744
|
+
SkillDetailResponseSchema = z3.object({
|
|
2745
|
+
skill: z3.object({
|
|
2587
2746
|
slug: SlugSchema,
|
|
2588
|
-
title:
|
|
2589
|
-
description:
|
|
2747
|
+
title: z3.string().min(1),
|
|
2748
|
+
description: z3.string(),
|
|
2590
2749
|
owner: PersonNameEmailSchema,
|
|
2591
|
-
created_at:
|
|
2592
|
-
license:
|
|
2593
|
-
min_floom:
|
|
2750
|
+
created_at: IsoDateTimeSchema2,
|
|
2751
|
+
license: z3.string().nullable().optional(),
|
|
2752
|
+
min_floom: z3.string().nullable().optional(),
|
|
2594
2753
|
latest: VersionRefSchema,
|
|
2595
|
-
works_with:
|
|
2596
|
-
files:
|
|
2597
|
-
versions:
|
|
2754
|
+
works_with: z3.array(TargetSchema),
|
|
2755
|
+
files: z3.array(FileMetadataSchema),
|
|
2756
|
+
versions: z3.array(VersionHistoryItemSchema)
|
|
2598
2757
|
}).strict()
|
|
2599
2758
|
}).strict();
|
|
2600
|
-
SkillVersionReadResponseSchema =
|
|
2601
|
-
skill:
|
|
2759
|
+
SkillVersionReadResponseSchema = z3.object({
|
|
2760
|
+
skill: z3.object({
|
|
2602
2761
|
slug: SlugSchema,
|
|
2603
|
-
title:
|
|
2604
|
-
description:
|
|
2762
|
+
title: z3.string().min(1),
|
|
2763
|
+
description: z3.string()
|
|
2605
2764
|
}).strict(),
|
|
2606
2765
|
version: VersionHistoryItemSchema,
|
|
2607
|
-
files:
|
|
2608
|
-
tree:
|
|
2766
|
+
files: z3.array(FileMetadataSchema),
|
|
2767
|
+
tree: z3.array(FileTreeEntrySchema),
|
|
2609
2768
|
selected_file: FileContentSchema.nullable(),
|
|
2610
|
-
file_contents:
|
|
2769
|
+
file_contents: z3.array(FileContentSchema)
|
|
2611
2770
|
}).strict();
|
|
2612
|
-
ShareCreateRequestSchema =
|
|
2613
|
-
ShareCreateResponseSchema =
|
|
2771
|
+
ShareCreateRequestSchema = z3.object({}).strict();
|
|
2772
|
+
ShareCreateResponseSchema = z3.object({
|
|
2614
2773
|
url: UrlSchema,
|
|
2615
|
-
token:
|
|
2774
|
+
token: z3.string().min(32)
|
|
2616
2775
|
}).strict();
|
|
2617
|
-
PublicShareGetResponseSchema =
|
|
2618
|
-
skill:
|
|
2619
|
-
title:
|
|
2620
|
-
description:
|
|
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:
|
|
2625
|
-
tree:
|
|
2783
|
+
files: z3.array(FileMetadataSchema),
|
|
2784
|
+
tree: z3.array(FileTreeEntrySchema),
|
|
2626
2785
|
selected_file: FileContentSchema.nullable(),
|
|
2627
|
-
file_contents:
|
|
2628
|
-
license:
|
|
2786
|
+
file_contents: z3.array(FileContentSchema),
|
|
2787
|
+
license: z3.string().nullable().optional()
|
|
2629
2788
|
}).strict();
|
|
2630
|
-
DeviceSessionStateSchema =
|
|
2789
|
+
DeviceSessionStateSchema = z3.enum([
|
|
2631
2790
|
"pending",
|
|
2632
2791
|
"approved",
|
|
2633
2792
|
"denied",
|
|
2634
2793
|
"expired"
|
|
2635
2794
|
]);
|
|
2636
|
-
DeviceSessionResponseSchema =
|
|
2795
|
+
DeviceSessionResponseSchema = z3.object({
|
|
2637
2796
|
state: DeviceSessionStateSchema,
|
|
2638
|
-
device:
|
|
2639
|
-
label:
|
|
2640
|
-
location:
|
|
2641
|
-
client:
|
|
2642
|
-
first_seen:
|
|
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 =
|
|
2804
|
+
DeviceSessionActionResponseSchema = z3.object({
|
|
2646
2805
|
state: DeviceSessionStateSchema
|
|
2647
2806
|
}).strict();
|
|
2648
|
-
CliLibraryStateSchema =
|
|
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 =
|
|
2815
|
+
CliLibraryTargetQuerySchema = z3.object({
|
|
2657
2816
|
target: TargetSchema
|
|
2658
2817
|
}).strict();
|
|
2659
|
-
CliLibrarySkillSchema =
|
|
2818
|
+
CliLibrarySkillSchema = z3.object({
|
|
2660
2819
|
slug: SlugSchema,
|
|
2661
|
-
title:
|
|
2662
|
-
description:
|
|
2820
|
+
title: z3.string().min(1),
|
|
2821
|
+
description: z3.string(),
|
|
2663
2822
|
version: VersionRefSchema,
|
|
2664
|
-
hash:
|
|
2823
|
+
hash: Sha256Schema2,
|
|
2665
2824
|
state: CliLibraryStateSchema,
|
|
2666
|
-
files:
|
|
2825
|
+
files: z3.array(FileContentSchema)
|
|
2667
2826
|
}).strict();
|
|
2668
|
-
CliLibraryResponseSchema =
|
|
2827
|
+
CliLibraryResponseSchema = z3.object({
|
|
2669
2828
|
workspace: WorkspaceSchema,
|
|
2670
2829
|
target: TargetSchema,
|
|
2671
|
-
generated_at:
|
|
2672
|
-
manifest_schema_version:
|
|
2673
|
-
hash_basis:
|
|
2674
|
-
full_hash:
|
|
2675
|
-
states:
|
|
2676
|
-
skills:
|
|
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 =
|
|
2837
|
+
LocalManifestSkillSchema = z3.object({
|
|
2679
2838
|
slug: SlugSchema,
|
|
2680
2839
|
version_seq: VersionSeqSchema,
|
|
2681
|
-
hash:
|
|
2840
|
+
hash: Sha256Schema2,
|
|
2682
2841
|
state: CliLibraryStateSchema,
|
|
2683
|
-
installed_paths:
|
|
2842
|
+
installed_paths: z3.array(z3.string().min(1))
|
|
2684
2843
|
}).strict();
|
|
2685
|
-
LocalManifestSchema =
|
|
2686
|
-
manifest_schema_version:
|
|
2844
|
+
LocalManifestSchema = z3.object({
|
|
2845
|
+
manifest_schema_version: z3.literal(1),
|
|
2687
2846
|
target: TargetSchema,
|
|
2688
2847
|
workspace_slug: SlugSchema,
|
|
2689
|
-
full_hash:
|
|
2690
|
-
hash_basis:
|
|
2691
|
-
installed_at:
|
|
2692
|
-
backup_path:
|
|
2693
|
-
skills:
|
|
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 =
|
|
2696
|
-
id:
|
|
2697
|
-
title:
|
|
2698
|
-
locked:
|
|
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 =
|
|
2702
|
-
last_pulled_at:
|
|
2860
|
+
AgentTargetSyncSchema = z3.object({
|
|
2861
|
+
last_pulled_at: IsoDateTimeSchema2.nullable()
|
|
2703
2862
|
}).strict();
|
|
2704
|
-
AgentMachineSchema =
|
|
2705
|
-
machine_id:
|
|
2706
|
-
machine_label:
|
|
2707
|
-
last_seen_at:
|
|
2708
|
-
target_sync:
|
|
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 =
|
|
2711
|
-
machines:
|
|
2712
|
-
total:
|
|
2869
|
+
AgentsListResponseSchema = z3.object({
|
|
2870
|
+
machines: z3.array(AgentMachineSchema),
|
|
2871
|
+
total: z3.number().int().nonnegative()
|
|
2713
2872
|
}).strict();
|
|
2714
|
-
ActivityEventSchema =
|
|
2873
|
+
ActivityEventSchema = z3.object({
|
|
2715
2874
|
id: IdSchema,
|
|
2716
|
-
event_name:
|
|
2717
|
-
source:
|
|
2718
|
-
target:
|
|
2719
|
-
skill_slug:
|
|
2720
|
-
created_at:
|
|
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 =
|
|
2723
|
-
events:
|
|
2724
|
-
total:
|
|
2881
|
+
ActivityFeedResponseSchema = z3.object({
|
|
2882
|
+
events: z3.array(ActivityEventSchema),
|
|
2883
|
+
total: z3.number().int().nonnegative()
|
|
2725
2884
|
}).strict();
|
|
2726
|
-
SkillSyncTargetEntrySchema =
|
|
2885
|
+
SkillSyncTargetEntrySchema = z3.object({
|
|
2727
2886
|
target: TargetSchema,
|
|
2728
|
-
last_pulled_at:
|
|
2887
|
+
last_pulled_at: IsoDateTimeSchema2
|
|
2729
2888
|
}).strict();
|
|
2730
|
-
SkillSyncMachineSchema =
|
|
2889
|
+
SkillSyncMachineSchema = z3.object({
|
|
2731
2890
|
machine_id: IdSchema,
|
|
2732
|
-
machine_label:
|
|
2733
|
-
targets:
|
|
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
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
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/
|
|
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(["
|
|
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
|
|
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
|
-
|
|
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
|
|
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/
|
|
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/
|
|
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
|
|
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/
|
|
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:
|
|
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/
|
|
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:
|
|
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/
|
|
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:
|
|
4553
|
-
type:
|
|
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/
|
|
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/
|
|
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
|
|
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
|
-
|
|
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
|
|
6670
|
-
const
|
|
6671
|
-
const
|
|
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",
|
|
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
|
|
6767
|
-
if (!
|
|
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
|
|
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
|
|
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/
|
|
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/
|
|
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/
|
|
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/
|
|
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")}
|
|
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:
|
|
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
|
}
|