@cogenta/plugins 0.1.3 → 0.3.1

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.
Files changed (44) hide show
  1. package/dist/host/worker-runner.d.ts +15 -0
  2. package/dist/host/worker-runner.d.ts.map +1 -1
  3. package/dist/host/worker-runner.js +10 -1
  4. package/dist/host/worker-runner.js.map +1 -1
  5. package/dist/index.d.ts +6 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +4 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/loader.d.ts +20 -0
  10. package/dist/loader.d.ts.map +1 -1
  11. package/dist/loader.js +44 -0
  12. package/dist/loader.js.map +1 -1
  13. package/dist/permissions/disabled.d.ts +7 -0
  14. package/dist/permissions/disabled.d.ts.map +1 -1
  15. package/dist/permissions/disabled.js +9 -0
  16. package/dist/permissions/disabled.js.map +1 -1
  17. package/dist/permissions/grants.d.ts +7 -0
  18. package/dist/permissions/grants.d.ts.map +1 -1
  19. package/dist/permissions/grants.js +5 -0
  20. package/dist/permissions/grants.js.map +1 -1
  21. package/dist/permissions/tables.d.ts +1 -0
  22. package/dist/permissions/tables.d.ts.map +1 -1
  23. package/dist/permissions/tables.js +18 -0
  24. package/dist/permissions/tables.js.map +1 -1
  25. package/dist/permissions/usage.d.ts +50 -0
  26. package/dist/permissions/usage.d.ts.map +1 -0
  27. package/dist/permissions/usage.js +66 -0
  28. package/dist/permissions/usage.js.map +1 -0
  29. package/dist/registries/marketplace-tables.d.ts +16 -0
  30. package/dist/registries/marketplace-tables.d.ts.map +1 -0
  31. package/dist/registries/marketplace-tables.js +50 -0
  32. package/dist/registries/marketplace-tables.js.map +1 -0
  33. package/dist/registries/marketplace.d.ts +170 -0
  34. package/dist/registries/marketplace.d.ts.map +1 -0
  35. package/dist/registries/marketplace.js +278 -0
  36. package/dist/registries/marketplace.js.map +1 -0
  37. package/dist/registries/skills.d.ts.map +1 -1
  38. package/dist/registries/skills.js +4 -1
  39. package/dist/registries/skills.js.map +1 -1
  40. package/dist/registries/skins.d.ts +10 -0
  41. package/dist/registries/skins.d.ts.map +1 -1
  42. package/dist/registries/skins.js +8 -3
  43. package/dist/registries/skins.js.map +1 -1
  44. package/package.json +6 -6
@@ -0,0 +1,50 @@
1
+ import { identifier, sql, unsafeRaw, } from '@cogenta/core';
2
+ export const MARKETPLACE_TABLES = {
3
+ installs: 'cogenta_marketplace_installs',
4
+ };
5
+ function textColumn(dialect, length) {
6
+ return unsafeRaw(dialect === 'sqlite' ? 'text' : `varchar(${length})`);
7
+ }
8
+ /**
9
+ * Owned by `@cogenta/plugins`, following `permissions/tables.ts`'s
10
+ * `ensurePluginTables` pattern exactly. One row per marketplace catalog item
11
+ * that has actually been installed — separate from the four submission
12
+ * registries (`./tables.js`), which track "may this be listed" (a review
13
+ * decision), never "is this active on this installation" (an install
14
+ * decision). `item_id` is the catalog entry's own id, not the plugin name:
15
+ * the catalog is the caller's concern (`createMarketplaceCatalog`), this
16
+ * table only remembers what was installed from it.
17
+ */
18
+ export async function ensureMarketplaceTables(db) {
19
+ const d = db.dialect;
20
+ const installs = identifier(MARKETPLACE_TABLES.installs, d);
21
+ const t255 = textColumn(d, 255);
22
+ const tLong = unsafeRaw(d === 'sqlite' ? 'text' : 'text');
23
+ await db.query(sql `
24
+ create table if not exists ${installs} (
25
+ item_id ${t255} not null primary key,
26
+ kind ${t255} not null,
27
+ display_name ${t255} not null,
28
+ reference ${tLong} not null,
29
+ plugin_name ${t255},
30
+ plugin_version ${t255},
31
+ signature_verified ${t255} not null,
32
+ installed_by ${t255},
33
+ installed_at ${t255} not null,
34
+ updated_at ${t255} not null,
35
+ enabled ${t255} not null default 'true'
36
+ )`);
37
+ // Fiche 29 task 1 — "activer/désactiver" as a real, separate column, not
38
+ // a schema migration: `create table if not exists` never re-runs on an
39
+ // existing table, so a pre-fiche-29 install row (created before this
40
+ // column existed) needs it added explicitly, `default` applying only to
41
+ // rows the `insert` itself creates. Every dialect here supports `add
42
+ // column ... default` (SQLite since 3.35 for `default`-only columns,
43
+ // Postgres and MySQL/MariaDB unconditionally) — same portable
44
+ // best-effort idiom `createIndexIfMissing` already uses for "already
45
+ // there, not an error".
46
+ await db
47
+ .query(sql `alter table ${installs} add column enabled ${t255} not null default 'true'`)
48
+ .catch(() => undefined);
49
+ }
50
+ //# sourceMappingURL=marketplace-tables.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marketplace-tables.js","sourceRoot":"","sources":["../../src/registries/marketplace-tables.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,UAAU,EAEV,GAAG,EACH,SAAS,GACV,MAAM,eAAe,CAAA;AAEtB,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,QAAQ,EAAE,8BAA8B;CAChC,CAAA;AAEV,SAAS,UAAU,CAAC,OAAwB,EAAE,MAAc;IAC1D,OAAO,SAAS,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,MAAM,GAAG,CAAC,CAAA;AACxE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,EAAkB;IAC9D,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAA;IACpB,MAAM,QAAQ,GAAG,UAAU,CAAC,kBAAkB,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;IAC3D,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IAC/B,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;IAEzD,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAA;iCACa,QAAQ;gBACzB,IAAI;aACP,IAAI;qBACI,IAAI;kBACP,KAAK;oBACH,IAAI;uBACD,IAAI;2BACA,IAAI;qBACV,IAAI;qBACJ,IAAI;mBACN,IAAI;gBACP,IAAI;MACd,CAAC,CAAA;IAEL,yEAAyE;IACzE,uEAAuE;IACvE,qEAAqE;IACrE,wEAAwE;IACxE,qEAAqE;IACrE,qEAAqE;IACrE,8DAA8D;IAC9D,qEAAqE;IACrE,wBAAwB;IACxB,MAAM,EAAE;SACL,KAAK,CAAC,GAAG,CAAA,eAAe,QAAQ,uBAAuB,IAAI,0BAA0B,CAAC;SACtF,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;AAC3B,CAAC"}
@@ -0,0 +1,170 @@
1
+ import { type DatabaseHandle } from '@cogenta/core';
2
+ import { type PluginCapabilityDescription } from '../permissions/describe.js';
3
+ import type { PluginDisableStore } from '../permissions/disabled.js';
4
+ import type { PluginGrantStore } from '../permissions/grants.js';
5
+ import type { PluginUsageStore } from '../permissions/usage.js';
6
+ /**
7
+ * L17 task 1 — "Registre consultable (recherche, catégories)".
8
+ *
9
+ * Scoped, deliberately, as a **local/embedded** catalog: the lot doc names a
10
+ * dependency on L13 task 8 (API keys) "si la marketplace est un service
11
+ * distinct interrogé par API" — L13 task 8 was never built in this
12
+ * repository, so there is no real remote marketplace service to call. This
13
+ * is an in-memory, read-only directory of installable items the caller
14
+ * assembles (e.g. `@cogenta/cli` wiring already-installed local plugins
15
+ * alongside a small example catalog) — not a second submission-review
16
+ * pipeline like the four `./tables.js` registries, and not a fetch to any
17
+ * external host.
18
+ */
19
+ export type MarketplaceItemKind = 'plugin' | 'theme' | 'skin' | 'skill';
20
+ export interface MarketplaceChangelogEntry {
21
+ readonly version: string;
22
+ readonly notes: string;
23
+ /** Fiche 29 task 5 — "date de la dernière mise à jour", read off the newest changelog entry when present. */
24
+ readonly releasedAt?: string;
25
+ }
26
+ export interface MarketplaceCatalogEntry {
27
+ readonly id: string;
28
+ readonly kind: MarketplaceItemKind;
29
+ readonly displayName: string;
30
+ readonly description: string;
31
+ /** Free-text category, used for the catalog's category filter. */
32
+ readonly category: string;
33
+ /**
34
+ * Opaque to the catalog itself — for `kind: 'plugin'`, an absolute local
35
+ * directory `loadMarketplacePlugin` can resolve. Never interpreted here.
36
+ */
37
+ readonly reference: string;
38
+ /** Fiche 29 task 5 — "Auteur, source" shown on the compatibility/trust panel before install. Caller-supplied, deployer-authored catalog metadata; never derived from the manifest (which has no author field). */
39
+ readonly author?: string;
40
+ readonly screenshots?: readonly string[];
41
+ readonly changelog?: readonly MarketplaceChangelogEntry[];
42
+ }
43
+ export interface MarketplaceCatalogFilter {
44
+ readonly kind?: MarketplaceItemKind;
45
+ /** Matched, case-insensitively, against `displayName`, `description` and `category`. */
46
+ readonly query?: string;
47
+ }
48
+ export interface MarketplaceCatalog {
49
+ list(filter?: MarketplaceCatalogFilter): readonly MarketplaceCatalogEntry[];
50
+ get(id: string): MarketplaceCatalogEntry | null;
51
+ }
52
+ /** A read-only in-memory catalog over a caller-supplied entry list. */
53
+ export declare function createMarketplaceCatalog(entries: readonly MarketplaceCatalogEntry[]): MarketplaceCatalog;
54
+ /** One installed marketplace item, as persisted. */
55
+ export interface MarketplaceInstallRecord {
56
+ readonly itemId: string;
57
+ readonly kind: MarketplaceItemKind;
58
+ readonly displayName: string;
59
+ readonly reference: string;
60
+ readonly pluginName: string | null;
61
+ readonly pluginVersion: string | null;
62
+ readonly signatureVerified: boolean;
63
+ readonly installedBy: string | null;
64
+ readonly installedAt: string;
65
+ readonly updatedAt: string;
66
+ /** Fiche 29 task 1 — the manual activate/deactivate toggle, independent of `@cogenta/plugins`' automatic `PluginDisableStore` (a timeout/memory/crash violation, task 6 of L7). Both can make a plugin non-runnable; this is only the human-chosen half. */
67
+ readonly enabled: boolean;
68
+ }
69
+ /** What viewing an item's "fiche détaillée" (task 3) needs, before installing. */
70
+ export interface MarketplacePreview {
71
+ readonly entry: MarketplaceCatalogEntry;
72
+ readonly supported: boolean;
73
+ readonly signatureVerified: boolean;
74
+ readonly capabilities: readonly (PluginCapabilityDescription & {
75
+ readonly capability: string;
76
+ })[];
77
+ /** Set when resolution/verification failed — the real `CogentaError` code, e.g. `PLUGIN_SIGNATURE_INVALID`. */
78
+ readonly error?: {
79
+ readonly code: string;
80
+ readonly message: string;
81
+ };
82
+ /**
83
+ * Fiche 29 task 5 — "Version de Cogenta requise, vérifiée avant
84
+ * l'installation, avec un refus clair". `null` only when resolution
85
+ * itself failed (`error` is set) — there is no manifest to check
86
+ * compatibility against. Computed by `loadMarketplacePlugin` from the
87
+ * `engineVersion` this installer was constructed with; `install`/`update`
88
+ * refuse honestly (`MARKETPLACE_ENGINE_INCOMPATIBLE`) rather than let an
89
+ * incompatible plugin fail at runtime instead.
90
+ */
91
+ readonly engineCompatible: boolean | null;
92
+ /** The resolvable manifest's own version — `null` only when resolution failed. Compared against an installed item's `pluginVersion` to answer "is an update available" (task 2). */
93
+ readonly latestVersion: string | null;
94
+ /** Fiche 29 task 5 — "source". Always `'registry'` when `supported`: `install`/`update` always call `loadMarketplacePlugin`, which classifies every marketplace item as registry-trust regardless of whether its `reference` happens to be a local path (see that function's own doc comment). */
95
+ readonly source: 'registry' | null;
96
+ }
97
+ export interface MarketplaceUpdateResult {
98
+ readonly record: MarketplaceInstallRecord;
99
+ /** Newly-declared capabilities the previous grants don't cover — never auto-granted, ever. */
100
+ readonly pendingApproval: readonly (PluginCapabilityDescription & {
101
+ readonly capability: string;
102
+ })[];
103
+ }
104
+ export interface MarketplaceInstaller {
105
+ /** Resolves and verifies signature — never installs, never throws for a bad signature (returns it in `error`). */
106
+ preview(entry: MarketplaceCatalogEntry): Promise<MarketplacePreview>;
107
+ /**
108
+ * Installs one catalog entry. **Only `kind: 'plugin'` is supported** —
109
+ * L17's own "pièges connus" line ("une marketplace est une nouvelle
110
+ * surface de confiance") is specifically about code execution, which only
111
+ * a plugin does; theme/skin/skill installation is out of scope for this
112
+ * pass and refused honestly (`MARKETPLACE_KIND_UNSUPPORTED`) rather than
113
+ * silently accepted with no real verification behind it.
114
+ *
115
+ * Always calls `loadMarketplacePlugin`, which always requires (and
116
+ * verifies) a signature — there is no parameter here, and none upstream,
117
+ * that can skip that call. A missing or invalid signature throws the real
118
+ * `PLUGIN_SIGNATURE_MISSING`/`PLUGIN_SIGNATURE_INVALID` and nothing is
119
+ * persisted.
120
+ */
121
+ install(entry: MarketplaceCatalogEntry, actorId: string | null): Promise<MarketplaceInstallRecord>;
122
+ /**
123
+ * Re-verifies signature against a (possibly new) catalog entry for an
124
+ * already-installed item. If the resolved manifest declares a capability
125
+ * no existing grant covers, the update is refused
126
+ * (`MARKETPLACE_UPDATE_REQUIRES_APPROVAL`) unless the caller passes
127
+ * `confirmPendingPermissions: true` — and even then, no capability is
128
+ * granted here: `PluginGrantStore.grant` is a separate, explicit step, so
129
+ * "confirming" only unblocks the version bump, never auto-grants.
130
+ */
131
+ update(entry: MarketplaceCatalogEntry, actorId: string | null, options?: {
132
+ readonly confirmPendingPermissions?: boolean;
133
+ }): Promise<MarketplaceUpdateResult>;
134
+ list(): Promise<readonly MarketplaceInstallRecord[]>;
135
+ get(itemId: string): Promise<MarketplaceInstallRecord | null>;
136
+ /**
137
+ * Fiche 29 task 4 — "désinstallation propre". `removeData: true` also
138
+ * revokes every active capability grant for the plugin
139
+ * (`PluginGrantStore.revokeAll`) and, when a disable/usage store was
140
+ * supplied to this installer, clears its auto-disable record and
141
+ * accumulated resource usage — irreversible, matching the router's own
142
+ * "confirmation forte" for this path. Without it (the default), only the
143
+ * install row is removed: grants, the disable record and usage history
144
+ * all survive, which is what makes a later reinstall able to pick up
145
+ * exactly where the plugin left off.
146
+ */
147
+ uninstall(itemId: string, options?: {
148
+ readonly removeData?: boolean;
149
+ }): Promise<void>;
150
+ /** Fiche 29 task 1 — the manual half of "activer/désactiver" (`MarketplaceInstallRecord.enabled`). Activating an item still auto-disabled (`PluginDisableStore`) does not by itself make it runnable again — that decision is `PluginDisableStore.enable`'s, deliberately kept a separate, explicit action (the router composes both). */
151
+ activate(itemId: string): Promise<MarketplaceInstallRecord>;
152
+ deactivate(itemId: string): Promise<MarketplaceInstallRecord>;
153
+ }
154
+ export interface MarketplaceInstallerOptions {
155
+ readonly trustedPublicKeys?: readonly string[];
156
+ readonly grantStore: PluginGrantStore;
157
+ readonly now?: () => number;
158
+ /**
159
+ * Cogenta's own version, checked against a resolved manifest's `engine`
160
+ * range (fiche 29 task 5). Passed straight through to
161
+ * `loadMarketplacePlugin` — see `LoadPluginOptions.engineVersion` for why
162
+ * the default is an honest placeholder rather than a fabricated pass.
163
+ */
164
+ readonly engineVersion?: string;
165
+ /** Fiche 29 task 4 — only consulted by `uninstall(id, { removeData: true })`; a plain uninstall never touches either store. */
166
+ readonly disableStore?: PluginDisableStore;
167
+ readonly usageStore?: PluginUsageStore;
168
+ }
169
+ export declare function createMarketplaceInstaller(db: DatabaseHandle, options: MarketplaceInstallerOptions): MarketplaceInstaller;
170
+ //# sourceMappingURL=marketplace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marketplace.d.ts","sourceRoot":"","sources":["../../src/registries/marketplace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,cAAc,EAAmB,MAAM,eAAe,CAAA;AAElF,OAAO,EAAsB,KAAK,2BAA2B,EAAE,MAAM,4BAA4B,CAAA;AACjG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAEhE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAG/D;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAA;AAEvE,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,6GAA6G;IAC7G,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAA;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,kNAAkN;IAClN,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,yBAAyB,EAAE,CAAA;CAC1D;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,CAAC,EAAE,mBAAmB,CAAA;IACnC,wFAAwF;IACxF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,MAAM,CAAC,EAAE,wBAAwB,GAAG,SAAS,uBAAuB,EAAE,CAAA;IAC3E,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,uBAAuB,GAAG,IAAI,CAAA;CAChD;AAaD,uEAAuE;AACvE,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,SAAS,uBAAuB,EAAE,GAC1C,kBAAkB,CAUpB;AAED,oDAAoD;AACpD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAA;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAA;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,4PAA4P;IAC5P,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AAED,kFAAkF;AAClF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,uBAAuB,CAAA;IACvC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAA;IACnC,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC,2BAA2B,GAAG;QAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAA;IACjG,+GAA+G;IAC/G,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;IACpE;;;;;;;;OAQG;IACH,QAAQ,CAAC,gBAAgB,EAAE,OAAO,GAAG,IAAI,CAAA;IACzC,oLAAoL;IACpL,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,kSAAkS;IAClS,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAA;CACnC;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAA;IACzC,8FAA8F;IAC9F,QAAQ,CAAC,eAAe,EAAE,SAAS,CAAC,2BAA2B,GAAG;QAChE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;KAC5B,CAAC,EAAE,CAAA;CACL;AAED,MAAM,WAAW,oBAAoB;IACnC,kHAAkH;IAClH,OAAO,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAA;IACpE;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,KAAK,EAAE,uBAAuB,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAA;IAClG;;;;;;;;OAQG;IACH,MAAM,CACJ,KAAK,EAAE,uBAAuB,EAC9B,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,yBAAyB,CAAC,EAAE,OAAO,CAAA;KAAE,GACzD,OAAO,CAAC,uBAAuB,CAAC,CAAA;IACnC,IAAI,IAAI,OAAO,CAAC,SAAS,wBAAwB,EAAE,CAAC,CAAA;IACpD,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC,CAAA;IAC7D;;;;;;;;;;OAUG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACrF,0UAA0U;IAC1U,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAA;IAC3D,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAA;CAC9D;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9C,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAA;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;IAC3B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,+HAA+H;IAC/H,QAAQ,CAAC,YAAY,CAAC,EAAE,kBAAkB,CAAA;IAC1C,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAA;CACvC;AA+DD,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,cAAc,EAClB,OAAO,EAAE,2BAA2B,GACnC,oBAAoB,CAgQtB"}
@@ -0,0 +1,278 @@
1
+ import { CogentaError, identifier, sql } from '@cogenta/core';
2
+ import { loadMarketplacePlugin } from '../loader.js';
3
+ import { describeCapability } from '../permissions/describe.js';
4
+ import { detectCapabilitiesNeedingApproval } from '../permissions/resolve.js';
5
+ import { MARKETPLACE_TABLES } from './marketplace-tables.js';
6
+ function matches(entry, filter) {
7
+ if (filter.kind !== undefined && entry.kind !== filter.kind)
8
+ return false;
9
+ if (filter.query === undefined || filter.query.trim() === '')
10
+ return true;
11
+ const needle = filter.query.trim().toLowerCase();
12
+ return (entry.displayName.toLowerCase().includes(needle) ||
13
+ entry.description.toLowerCase().includes(needle) ||
14
+ entry.category.toLowerCase().includes(needle));
15
+ }
16
+ /** A read-only in-memory catalog over a caller-supplied entry list. */
17
+ export function createMarketplaceCatalog(entries) {
18
+ const byId = new Map(entries.map((entry) => [entry.id, entry]));
19
+ return {
20
+ list(filter = {}) {
21
+ return entries.filter((entry) => matches(entry, filter));
22
+ },
23
+ get(id) {
24
+ return byId.get(id) ?? null;
25
+ },
26
+ };
27
+ }
28
+ function toRecord(row) {
29
+ return {
30
+ itemId: row.item_id,
31
+ kind: row.kind,
32
+ displayName: row.display_name,
33
+ reference: row.reference,
34
+ pluginName: row.plugin_name,
35
+ pluginVersion: row.plugin_version,
36
+ signatureVerified: row.signature_verified === 'true',
37
+ installedBy: row.installed_by,
38
+ installedAt: row.installed_at,
39
+ updatedAt: row.updated_at,
40
+ // `enabled` is nullable at the SQL level only because a row created
41
+ // before fiche 29's `alter table ... add column` ran has no explicit
42
+ // value in older engines that ignore `default` on backfill — treated as
43
+ // "still active", matching every pre-existing install's real state.
44
+ enabled: row.enabled !== 'false',
45
+ };
46
+ }
47
+ function engineIncompatible(entry, manifest) {
48
+ return new CogentaError({
49
+ code: 'MARKETPLACE_ENGINE_INCOMPATIBLE',
50
+ message: `"${entry.displayName}" requires Cogenta "${manifest.engine}", which this installation does not satisfy.`,
51
+ hint: 'Upgrade Cogenta, or choose a version of this item compatible with the current installation.',
52
+ details: { itemId: entry.id, engine: manifest.engine },
53
+ });
54
+ }
55
+ function unsupportedKind(entry) {
56
+ return new CogentaError({
57
+ code: 'MARKETPLACE_KIND_UNSUPPORTED',
58
+ message: `The marketplace does not install "${entry.kind}" items yet — only "plugin".`,
59
+ hint: 'Themes, skins and skills go through their own registries (@cogenta/plugins’ createThemeRegistry/createSkinGallery/createSkillRegistry) for now.',
60
+ details: { itemId: entry.id, kind: entry.kind },
61
+ });
62
+ }
63
+ function describeAll(capabilities) {
64
+ return capabilities.map((capability) => ({ capability, ...describeCapability(capability) }));
65
+ }
66
+ export function createMarketplaceInstaller(db, options) {
67
+ const installs = identifier(MARKETPLACE_TABLES.installs, db.dialect);
68
+ const now = options.now ?? Date.now;
69
+ const trustedPublicKeys = options.trustedPublicKeys ?? [];
70
+ const grantStore = options.grantStore;
71
+ const engineVersion = options.engineVersion;
72
+ async function getRecord(itemId) {
73
+ const result = await db.query(sql `
74
+ select * from ${installs} where item_id = ${itemId}`);
75
+ const row = result.rows[0];
76
+ return row === undefined ? null : toRecord(row);
77
+ }
78
+ async function setEnabled(itemId, enabled) {
79
+ await db.query(sql `
80
+ update ${installs} set enabled = ${String(enabled)}, updated_at = ${new Date(now()).toISOString()}
81
+ where item_id = ${itemId}`);
82
+ const record = await getRecord(itemId);
83
+ if (record === null) {
84
+ throw new CogentaError({
85
+ code: 'MARKETPLACE_NOT_INSTALLED',
86
+ message: `"${itemId}" is not installed.`,
87
+ hint: 'Install it first.',
88
+ details: { itemId },
89
+ });
90
+ }
91
+ return record;
92
+ }
93
+ async function resolveOrError(entry) {
94
+ try {
95
+ const resolved = await loadMarketplacePlugin(entry.reference, {
96
+ trustedPublicKeys,
97
+ ...(engineVersion === undefined ? {} : { engineVersion }),
98
+ });
99
+ return {
100
+ ok: true,
101
+ manifest: resolved.manifest,
102
+ signatureVerified: resolved.signatureVerified,
103
+ engineCompatible: engineVersion === undefined ? null : resolved.engineCompatible,
104
+ };
105
+ }
106
+ catch (error) {
107
+ if (error instanceof CogentaError) {
108
+ return { ok: false, error: { code: error.code, message: error.message } };
109
+ }
110
+ throw error;
111
+ }
112
+ }
113
+ return {
114
+ async preview(entry) {
115
+ if (entry.kind !== 'plugin') {
116
+ return {
117
+ entry,
118
+ supported: false,
119
+ signatureVerified: false,
120
+ capabilities: [],
121
+ engineCompatible: null,
122
+ latestVersion: null,
123
+ source: null,
124
+ };
125
+ }
126
+ const resolution = await resolveOrError(entry);
127
+ if (!resolution.ok) {
128
+ return {
129
+ entry,
130
+ supported: true,
131
+ signatureVerified: false,
132
+ capabilities: [],
133
+ error: resolution.error,
134
+ engineCompatible: null,
135
+ latestVersion: null,
136
+ source: null,
137
+ };
138
+ }
139
+ return {
140
+ entry,
141
+ supported: true,
142
+ signatureVerified: resolution.signatureVerified,
143
+ capabilities: describeAll(resolution.manifest.capabilities),
144
+ engineCompatible: resolution.engineCompatible,
145
+ latestVersion: resolution.manifest.version,
146
+ source: 'registry',
147
+ };
148
+ },
149
+ async install(entry, actorId) {
150
+ if (entry.kind !== 'plugin')
151
+ throw unsupportedKind(entry);
152
+ // Never a soft catch here: an invalid/missing signature throws and
153
+ // nothing below runs — this is the one line the whole task hinges on.
154
+ const resolved = await loadMarketplacePlugin(entry.reference, {
155
+ trustedPublicKeys,
156
+ ...(engineVersion === undefined ? {} : { engineVersion }),
157
+ });
158
+ // Fiche 29 task 5 — refused BEFORE anything is persisted, exactly
159
+ // like the signature check above: an incompatible version never gets
160
+ // a chance to fail later at runtime instead. Only enforced once this
161
+ // installer was configured with a real `engineVersion` — see
162
+ // `resolveOrError`'s doc comment for why the default placeholder
163
+ // must never manufacture a refusal.
164
+ if (engineVersion !== undefined && !resolved.engineCompatible) {
165
+ throw engineIncompatible(entry, resolved.manifest);
166
+ }
167
+ const timestamp = new Date(now()).toISOString();
168
+ // Delete-then-insert rather than a dialect-specific upsert (`on
169
+ // conflict` on Postgres/SQLite, `on duplicate key` on MySQL) — the
170
+ // same portable idiom `PluginGrantStore.grant` already uses
171
+ // (`../permissions/grants.js`) for the identical "re-installing is
172
+ // idempotent, not a duplicate row" requirement. A (re)install always
173
+ // resets `enabled` to `true` — a fresh install is never born disabled.
174
+ await db.query(sql `delete from ${installs} where item_id = ${entry.id}`);
175
+ await db.query(sql `
176
+ insert into ${installs}
177
+ (item_id, kind, display_name, reference, plugin_name, plugin_version,
178
+ signature_verified, installed_by, installed_at, updated_at, enabled)
179
+ values
180
+ (${entry.id}, ${entry.kind}, ${entry.displayName}, ${entry.reference},
181
+ ${resolved.manifest.name}, ${resolved.manifest.version},
182
+ ${String(resolved.signatureVerified)}, ${actorId}, ${timestamp}, ${timestamp}, ${'true'})`);
183
+ return {
184
+ itemId: entry.id,
185
+ kind: entry.kind,
186
+ displayName: entry.displayName,
187
+ reference: entry.reference,
188
+ pluginName: resolved.manifest.name,
189
+ pluginVersion: resolved.manifest.version,
190
+ signatureVerified: resolved.signatureVerified,
191
+ installedBy: actorId,
192
+ installedAt: timestamp,
193
+ updatedAt: timestamp,
194
+ enabled: true,
195
+ };
196
+ },
197
+ async update(entry, actorId, updateOptions = {}) {
198
+ if (entry.kind !== 'plugin')
199
+ throw unsupportedKind(entry);
200
+ const existing = await getRecord(entry.id);
201
+ if (existing === null) {
202
+ throw new CogentaError({
203
+ code: 'MARKETPLACE_NOT_INSTALLED',
204
+ message: `"${entry.displayName}" is not installed, so it cannot be updated.`,
205
+ hint: 'Install it first.',
206
+ details: { itemId: entry.id },
207
+ });
208
+ }
209
+ // Signature is verified before anything else here too — an update
210
+ // never trusts the previously-installed state as a substitute for
211
+ // re-checking the new reference.
212
+ const resolved = await loadMarketplacePlugin(entry.reference, {
213
+ trustedPublicKeys,
214
+ ...(engineVersion === undefined ? {} : { engineVersion }),
215
+ });
216
+ if (engineVersion !== undefined && !resolved.engineCompatible) {
217
+ throw engineIncompatible(entry, resolved.manifest);
218
+ }
219
+ const previousGrants = existing.pluginName === null ? [] : await grantStore.listGrants(existing.pluginName);
220
+ const pending = detectCapabilitiesNeedingApproval(resolved.manifest, previousGrants.map((grant) => grant.capability));
221
+ if (pending.length > 0 && updateOptions.confirmPendingPermissions !== true) {
222
+ throw new CogentaError({
223
+ code: 'MARKETPLACE_UPDATE_REQUIRES_APPROVAL',
224
+ message: `Updating "${entry.displayName}" would request ${pending.length} new permission(s) — this never applies silently.`,
225
+ hint: 'Review the new permissions and retry with confirmPendingPermissions: true. No capability is granted automatically even then — grant it explicitly afterward.',
226
+ details: { itemId: entry.id, pending },
227
+ });
228
+ }
229
+ const timestamp = new Date(now()).toISOString();
230
+ await db.query(sql `
231
+ update ${installs} set
232
+ display_name = ${entry.displayName},
233
+ reference = ${entry.reference},
234
+ plugin_name = ${resolved.manifest.name},
235
+ plugin_version = ${resolved.manifest.version},
236
+ signature_verified = ${String(resolved.signatureVerified)},
237
+ installed_by = ${actorId},
238
+ updated_at = ${timestamp}
239
+ where item_id = ${entry.id}`);
240
+ const record = await getRecord(entry.id);
241
+ if (record === null) {
242
+ throw new CogentaError({
243
+ code: 'MARKETPLACE_NOT_INSTALLED',
244
+ message: `"${entry.displayName}" disappeared during its own update.`,
245
+ hint: 'Retry the update.',
246
+ details: { itemId: entry.id },
247
+ });
248
+ }
249
+ return { record, pendingApproval: describeAll(pending) };
250
+ },
251
+ async list() {
252
+ const result = await db.query(sql `
253
+ select * from ${installs} order by installed_at asc`);
254
+ return result.rows.map(toRecord);
255
+ },
256
+ async get(itemId) {
257
+ return getRecord(itemId);
258
+ },
259
+ async uninstall(itemId, uninstallOptions = {}) {
260
+ if (uninstallOptions.removeData === true) {
261
+ const record = await getRecord(itemId);
262
+ if (record?.pluginName !== null && record?.pluginName !== undefined) {
263
+ await grantStore.revokeAll(record.pluginName);
264
+ await options.disableStore?.enable(record.pluginName);
265
+ await options.usageStore?.clearUsage(record.pluginName);
266
+ }
267
+ }
268
+ await db.query(sql `delete from ${installs} where item_id = ${itemId}`);
269
+ },
270
+ async activate(itemId) {
271
+ return setEnabled(itemId, true);
272
+ },
273
+ async deactivate(itemId) {
274
+ return setEnabled(itemId, false);
275
+ },
276
+ };
277
+ }
278
+ //# sourceMappingURL=marketplace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marketplace.js","sourceRoot":"","sources":["../../src/registries/marketplace.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/registries/skills.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,cAAc,EAA0B,MAAM,eAAe,CAAA;AAGzF,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAA;AAEvE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,6FAA6F;IAC7F,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAA;IACtC,kGAAkG;IAClG,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,sFAAsF;IACtF,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAErD,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAA;CAAE,GAC3D;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GACpD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAA;CAAE,CAAA;AAEpG,MAAM,WAAW,aAAa;IAC5B;;;;;;;OAOG;IACH,MAAM,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAA;IAClE,2EAA2E;IAC3E,MAAM,CACJ,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,mBAAmB,EAC7B,cAAc,EAAE,MAAM,EACtB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC,CAAA;IAC7B,YAAY,IAAI,OAAO,CAAC,SAAS,oBAAoB,EAAE,CAAC,CAAA;IACxD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAA;CACtD;AAoCD,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,cAAc,EAClB,GAAG,GAAE,MAAM,MAAiB,GAC3B,aAAa,CAoGf"}
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/registries/skills.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,cAAc,EAA0B,MAAM,eAAe,CAAA;AAGzF,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAA;AAEvE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,6FAA6F;IAC7F,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAA;IACtC,kGAAkG;IAClG,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,sFAAsF;IACtF,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAErD,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAA;CAAE,GAC3D;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GACpD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAA;CAAE,CAAA;AAEpG,MAAM,WAAW,aAAa;IAC5B;;;;;;;OAOG;IACH,MAAM,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAA;IAClE,2EAA2E;IAC3E,MAAM,CACJ,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,mBAAmB,EAC7B,cAAc,EAAE,MAAM,EACtB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC,CAAA;IAC7B,YAAY,IAAI,OAAO,CAAC,SAAS,oBAAoB,EAAE,CAAC,CAAA;IACxD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAA;CACtD;AAoCD,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,cAAc,EAClB,GAAG,GAAE,MAAM,MAAiB,GAC3B,aAAa,CAuGf"}
@@ -32,7 +32,10 @@ export function createSkillRegistry(db, now = Date.now) {
32
32
  try {
33
33
  const { metadata } = parseSkillFile(input.displayName, input.rawContent);
34
34
  skillName = metadata.name;
35
- skillVersion = metadata.version;
35
+ // `version` is optional on a skill file since L24 task 4 (a real
36
+ // Claude Code/Codex `SKILL.md` never carries one) — the marketplace
37
+ // still records whatever the submitter provided, `null` if absent.
38
+ skillVersion = metadata.version ?? null;
36
39
  }
37
40
  catch (error) {
38
41
  status = 'rejected';
@@ -1 +1 @@
1
- {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/registries/skills.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/registries/skills.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,16 @@ export interface SkinGalleryEntry {
17
17
  readonly rejectionCode: string | null;
18
18
  readonly rejectionReason: string | null;
19
19
  readonly submittedAt: string;
20
+ /**
21
+ * The token JSON the submitter sent, parsed back out — the caller that
22
+ * turns this into an admin-facing gallery card (fiche 14 task 1) needs
23
+ * more than a name and a verdict to actually render a swatch or apply the
24
+ * skin. `null` on a rejected entry: a rejected skin never made it past
25
+ * `validateSkin`, so nothing here can be trusted to be a well-shaped token
26
+ * tree, and offering it anyway would invite a caller to render or apply a
27
+ * skin the gate has already refused.
28
+ */
29
+ readonly tokens: Record<string, unknown> | null;
20
30
  }
21
31
  export interface SkinGallery {
22
32
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"skins.d.ts","sourceRoot":"","sources":["../../src/registries/skins.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,cAAc,EAA0B,MAAM,eAAe,CAAA;AAIzF,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,UAAU,CAAA;AAE1D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,sGAAsG;IACtG,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAA;IACrC,qGAAqG;IACrG,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IACvC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED,MAAM,WAAW,WAAW;IAC1B;;;;;OAKG;IACH,MAAM,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAC7D,YAAY,IAAI,OAAO,CAAC,SAAS,gBAAgB,EAAE,CAAC,CAAA;IACpD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAA;CAClD;AA0BD,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,cAAc,EAAE,GAAG,GAAE,MAAM,MAAiB,GAAG,WAAW,CAqD/F"}
1
+ {"version":3,"file":"skins.d.ts","sourceRoot":"","sources":["../../src/registries/skins.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,cAAc,EAA0B,MAAM,eAAe,CAAA;AAIzF,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,UAAU,CAAA;AAE1D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,sGAAsG;IACtG,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAA;IACrC,qGAAqG;IACrG,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IACvC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B;;;;;;;;OAQG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;CAChD;AAED,MAAM,WAAW,WAAW;IAC1B;;;;;OAKG;IACH,MAAM,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAC7D,YAAY,IAAI,OAAO,CAAC,SAAS,gBAAgB,EAAE,CAAC,CAAA;IACpD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAA;CAClD;AAgCD,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,cAAc,EAAE,GAAG,GAAE,MAAM,MAAiB,GAAG,WAAW,CAsD/F"}
@@ -2,15 +2,19 @@ import { CogentaError, identifier, newId, sql } from '@cogenta/core';
2
2
  import { validateSkin } from '@cogenta/render';
3
3
  import { REGISTRY_TABLES } from './tables.js';
4
4
  function toEntry(row) {
5
+ const status = row.status === 'accepted' ? 'accepted' : 'rejected';
5
6
  return {
6
7
  id: row.id,
7
8
  submitterId: row.submitter_id,
8
9
  displayName: row.display_name,
9
10
  description: row.description,
10
- status: row.status === 'accepted' ? 'accepted' : 'rejected',
11
+ status,
11
12
  rejectionCode: row.rejection_code,
12
13
  rejectionReason: row.rejection_reason,
13
14
  submittedAt: row.submitted_at,
15
+ tokens: status === 'accepted' && typeof row.tokens_json === 'string'
16
+ ? JSON.parse(row.tokens_json)
17
+ : null,
14
18
  };
15
19
  }
16
20
  export function createSkinGallery(db, now = Date.now) {
@@ -44,18 +48,19 @@ export function createSkinGallery(db, now = Date.now) {
44
48
  status,
45
49
  rejectionCode,
46
50
  rejectionReason,
51
+ tokens: status === 'accepted' ? input.tokens : null,
47
52
  submittedAt,
48
53
  };
49
54
  },
50
55
  async listAccepted() {
51
56
  const result = await db.query(sql `
52
- select id, submitter_id, display_name, description, status, rejection_code, rejection_reason, submitted_at
57
+ select id, submitter_id, display_name, description, tokens_json, status, rejection_code, rejection_reason, submitted_at
53
58
  from ${skins} where status = 'accepted' order by submitted_at asc`);
54
59
  return result.rows.map(toEntry);
55
60
  },
56
61
  async get(id) {
57
62
  const result = await db.query(sql `
58
- select id, submitter_id, display_name, description, status, rejection_code, rejection_reason, submitted_at
63
+ select id, submitter_id, display_name, description, tokens_json, status, rejection_code, rejection_reason, submitted_at
59
64
  from ${skins} where id = ${id}`);
60
65
  const row = result.rows[0];
61
66
  return row === undefined ? null : toEntry(row);