@cogenta/plugins 0.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.
Files changed (86) hide show
  1. package/dist/guest/sandbox-entry.mjs +155 -0
  2. package/dist/host/capabilities.d.ts +46 -0
  3. package/dist/host/capabilities.d.ts.map +1 -0
  4. package/dist/host/capabilities.js +105 -0
  5. package/dist/host/capabilities.js.map +1 -0
  6. package/dist/host/protocol.d.ts +58 -0
  7. package/dist/host/protocol.d.ts.map +1 -0
  8. package/dist/host/protocol.js +10 -0
  9. package/dist/host/protocol.js.map +1 -0
  10. package/dist/host/worker-runner.d.ts +92 -0
  11. package/dist/host/worker-runner.d.ts.map +1 -0
  12. package/dist/host/worker-runner.js +196 -0
  13. package/dist/host/worker-runner.js.map +1 -0
  14. package/dist/index.d.ts +34 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +20 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/loader.d.ts +81 -0
  19. package/dist/loader.d.ts.map +1 -0
  20. package/dist/loader.js +190 -0
  21. package/dist/loader.js.map +1 -0
  22. package/dist/manifest.d.ts +93 -0
  23. package/dist/manifest.d.ts.map +1 -0
  24. package/dist/manifest.js +197 -0
  25. package/dist/manifest.js.map +1 -0
  26. package/dist/permissions/describe.d.ts +22 -0
  27. package/dist/permissions/describe.d.ts.map +1 -0
  28. package/dist/permissions/describe.js +158 -0
  29. package/dist/permissions/describe.js.map +1 -0
  30. package/dist/permissions/disabled.d.ts +25 -0
  31. package/dist/permissions/disabled.d.ts.map +1 -0
  32. package/dist/permissions/disabled.js +29 -0
  33. package/dist/permissions/disabled.js.map +1 -0
  34. package/dist/permissions/grants.d.ts +22 -0
  35. package/dist/permissions/grants.d.ts.map +1 -0
  36. package/dist/permissions/grants.js +31 -0
  37. package/dist/permissions/grants.js.map +1 -0
  38. package/dist/permissions/resolve.d.ts +47 -0
  39. package/dist/permissions/resolve.d.ts.map +1 -0
  40. package/dist/permissions/resolve.js +51 -0
  41. package/dist/permissions/resolve.js.map +1 -0
  42. package/dist/permissions/review.d.ts +50 -0
  43. package/dist/permissions/review.d.ts.map +1 -0
  44. package/dist/permissions/review.js +46 -0
  45. package/dist/permissions/review.js.map +1 -0
  46. package/dist/permissions/tables.d.ts +18 -0
  47. package/dist/permissions/tables.d.ts.map +1 -0
  48. package/dist/permissions/tables.js +48 -0
  49. package/dist/permissions/tables.js.map +1 -0
  50. package/dist/registries/plugins.d.ts +74 -0
  51. package/dist/registries/plugins.d.ts.map +1 -0
  52. package/dist/registries/plugins.js +127 -0
  53. package/dist/registries/plugins.js.map +1 -0
  54. package/dist/registries/skills.d.ts +54 -0
  55. package/dist/registries/skills.d.ts.map +1 -0
  56. package/dist/registries/skills.js +113 -0
  57. package/dist/registries/skills.js.map +1 -0
  58. package/dist/registries/skins.d.ts +33 -0
  59. package/dist/registries/skins.d.ts.map +1 -0
  60. package/dist/registries/skins.js +65 -0
  61. package/dist/registries/skins.js.map +1 -0
  62. package/dist/registries/tables.d.ts +44 -0
  63. package/dist/registries/tables.d.ts.map +1 -0
  64. package/dist/registries/tables.js +118 -0
  65. package/dist/registries/tables.js.map +1 -0
  66. package/dist/registries/themes.d.ts +59 -0
  67. package/dist/registries/themes.d.ts.map +1 -0
  68. package/dist/registries/themes.js +82 -0
  69. package/dist/registries/themes.js.map +1 -0
  70. package/dist/semver.d.ts +24 -0
  71. package/dist/semver.d.ts.map +1 -0
  72. package/dist/semver.js +93 -0
  73. package/dist/semver.js.map +1 -0
  74. package/dist/signing/keys.d.ts +18 -0
  75. package/dist/signing/keys.d.ts.map +1 -0
  76. package/dist/signing/keys.js +15 -0
  77. package/dist/signing/keys.js.map +1 -0
  78. package/dist/signing/sign.d.ts +35 -0
  79. package/dist/signing/sign.d.ts.map +1 -0
  80. package/dist/signing/sign.js +63 -0
  81. package/dist/signing/sign.js.map +1 -0
  82. package/dist/signing/verify.d.ts +40 -0
  83. package/dist/signing/verify.d.ts.map +1 -0
  84. package/dist/signing/verify.js +73 -0
  85. package/dist/signing/verify.js.map +1 -0
  86. package/package.json +46 -0
@@ -0,0 +1,93 @@
1
+ /**
2
+ * `definePlugin` is the only door into the plugin model, mirroring
3
+ * `defineCollection` (`@cogenta/schema`) — checked eagerly, at import time,
4
+ * because every later L7 task (worker isolation, SDK capability
5
+ * translation, the permission screen, signing) trusts this manifest
6
+ * completely. A mistake caught here costs a restart; the same mistake
7
+ * caught after a plugin is already granted capabilities costs a
8
+ * compromised site — 90% of WordPress compromises go through a plugin
9
+ * (docs/lots/L7-extensibilite.md § Objectif).
10
+ *
11
+ * Every issue is collected and reported at once (same reasoning as
12
+ * `schemaError` in `@cogenta/schema`): fixing a manifest one refusal at a
13
+ * time is a game of whack-a-mole an author shouldn't have to play.
14
+ */
15
+ /** One thing wrong with a manifest, located by a dotted path. */
16
+ export interface PluginManifestIssue {
17
+ readonly path: string;
18
+ readonly message: string;
19
+ }
20
+ /**
21
+ * A block a plugin provides outside the frozen contract B vocabulary. The
22
+ * fallback is part of the SHAPE, not a separate later check: "un bloc sans
23
+ * fallback est refusé" (docs/lots/L7-extensibilite.md § Manifeste) is a
24
+ * property of what a block provision IS, not something bolted on after the
25
+ * fact — carrying it here now avoids a breaking manifest-shape change once
26
+ * block registration is actually built (a later task).
27
+ */
28
+ export interface PluginBlockProvision {
29
+ readonly name: string;
30
+ /** The vocabulary block (e.g. `prose`) a renderer falls back to when this plugin is absent or its block is unrecognised. */
31
+ readonly fallback: string;
32
+ }
33
+ /**
34
+ * What a plugin brings, per "## Ce qu'un plugin peut apporter"
35
+ * (docs/lots/L7-extensibilite.md, lines 38-46). The manifest example in the
36
+ * lot doc only shows `tools`/`blocks`/`fields`/`channels`, but the
37
+ * surrounding prose names drivers, skills and event subscriptions as
38
+ * equally real things a plugin can provide — those slots are added here
39
+ * now so a later task doesn't have to widen this shape under a frozen
40
+ * contract. All optional: a plugin providing nothing new (e.g. a
41
+ * pure-consumer integration) is a legitimate, empty `provides`.
42
+ */
43
+ export interface PluginProvides {
44
+ readonly tools?: readonly string[];
45
+ readonly blocks?: readonly PluginBlockProvision[];
46
+ readonly fields?: readonly string[];
47
+ readonly channels?: readonly string[];
48
+ readonly drivers?: readonly string[];
49
+ readonly skills?: readonly string[];
50
+ readonly eventSubscriptions?: readonly string[];
51
+ }
52
+ export declare const PLUGIN_RUNTIMES: readonly ['server'];
53
+ export type PluginRuntime = (typeof PLUGIN_RUNTIMES)[number];
54
+ export interface PluginManifest {
55
+ /** npm-scoped or plain package name, e.g. `@auteur/mon-plugin`. */
56
+ readonly name: string;
57
+ /** Exact semver, e.g. `1.0.0`. */
58
+ readonly version: string;
59
+ /** A semver range this plugin declares compatibility with, e.g. `^1.0.0`. */
60
+ readonly engine: string;
61
+ /** Capability strings this plugin requests — see `PLUGIN_CAPABILITY_NAMES`. */
62
+ readonly capabilities: readonly string[];
63
+ readonly provides: PluginProvides;
64
+ readonly runtime: PluginRuntime;
65
+ /** Whether this plugin runs in an isolated worker (task 3) — which registry it may join is a later task's concern, not this schema's. */
66
+ readonly isolated: boolean;
67
+ }
68
+ /**
69
+ * The known plugin capability vocabulary. Grounded in contract C's frozen
70
+ * tool-permission taxonomy (`docs/04-contrats.md` § "Taxonomie des
71
+ * permissions": `content.*`, `media.*`, `schema.read`, `site.config_*`,
72
+ * `deps.*`, `build.trigger`, `deploy.trigger`, `http.fetch`,
73
+ * `channel.send`, `agent.delegate`, `memory.*`) rather than a parallel
74
+ * invention — a plugin providing an agent tool declares the same
75
+ * permission names an agent's own tool manifest already uses. `storage.read`
76
+ * / `storage.write` are added beyond contract C: plugins get their own
77
+ * prefix-confined storage (a concept agents' tool taxonomy doesn't need),
78
+ * and the lot doc's own manifest example (`storage.write:plugins/mon-plugin`)
79
+ * requires it to exist.
80
+ */
81
+ export declare const PLUGIN_CAPABILITY_NAMES: readonly ['content.read', 'content.write_draft', 'content.publish', 'content.delete', 'media.read', 'media.write', 'schema.read', 'site.config_read', 'site.config_write', 'deps.scan', 'deps.patch', 'build.trigger', 'deploy.trigger', 'http.fetch', 'storage.read', 'storage.write', 'channel.send', 'agent.delegate', 'memory.read', 'memory.write'];
82
+ export type PluginCapabilityName = (typeof PLUGIN_CAPABILITY_NAMES)[number];
83
+ /**
84
+ * Validates and freezes a plugin manifest. Every hard-refusal rule the lot
85
+ * specifies (`docs/lots/L7-extensibilite.md` § Manifeste) is enforced here:
86
+ * `http.fetch` without an explicit domain, a storage capability outside the
87
+ * plugin's own prefix, an unknown capability, and a block without a
88
+ * fallback are all refused with a single, complete error listing every
89
+ * issue at once — never a partial refusal an author has to rediscover one
90
+ * `definePlugin` call at a time.
91
+ */
92
+ export declare function definePlugin(input: PluginManifest): PluginManifest;
93
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AAEH,iEAAiE;AACjE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,4HAA4H;IAC5H,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAA;IACjD,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAChD;AAED,eAAO,MAAM,eAAe,YAAI,QAAQ,CAAU,CAAA;AAClD,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAA;AAE5D,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,kCAAkC;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,+EAA+E;IAC/E,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;IACxC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAA;IACjC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;IAC/B,yIAAyI;IACzI,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,uBAAuB,YAClC,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,mBAAmB,EACnB,WAAW,EACX,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,cAAc,CACN,CAAA;AACV,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAA;AAiK3E;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAYlE"}
@@ -0,0 +1,197 @@
1
+ import { CogentaError } from '@cogenta/core';
2
+ export const PLUGIN_RUNTIMES = ['server'];
3
+ /**
4
+ * The known plugin capability vocabulary. Grounded in contract C's frozen
5
+ * tool-permission taxonomy (`docs/04-contrats.md` § "Taxonomie des
6
+ * permissions": `content.*`, `media.*`, `schema.read`, `site.config_*`,
7
+ * `deps.*`, `build.trigger`, `deploy.trigger`, `http.fetch`,
8
+ * `channel.send`, `agent.delegate`, `memory.*`) rather than a parallel
9
+ * invention — a plugin providing an agent tool declares the same
10
+ * permission names an agent's own tool manifest already uses. `storage.read`
11
+ * / `storage.write` are added beyond contract C: plugins get their own
12
+ * prefix-confined storage (a concept agents' tool taxonomy doesn't need),
13
+ * and the lot doc's own manifest example (`storage.write:plugins/mon-plugin`)
14
+ * requires it to exist.
15
+ */
16
+ export const PLUGIN_CAPABILITY_NAMES = [
17
+ 'content.read',
18
+ 'content.write_draft',
19
+ 'content.publish',
20
+ 'content.delete',
21
+ 'media.read',
22
+ 'media.write',
23
+ 'schema.read',
24
+ 'site.config_read',
25
+ 'site.config_write',
26
+ 'deps.scan',
27
+ 'deps.patch',
28
+ 'build.trigger',
29
+ 'deploy.trigger',
30
+ 'http.fetch',
31
+ 'storage.read',
32
+ 'storage.write',
33
+ 'channel.send',
34
+ 'agent.delegate',
35
+ 'memory.read',
36
+ 'memory.write',
37
+ ];
38
+ /**
39
+ * Capabilities whose string carries a colon-suffixed parameter, per the
40
+ * lot doc's own example (`http.fetch:api.exemple.com`,
41
+ * `storage.write:plugins/mon-plugin`) — never a bare name, and never `*`.
42
+ */
43
+ const PARAMETERIZED_CAPABILITIES = new Set([
44
+ 'http.fetch',
45
+ 'storage.read',
46
+ 'storage.write',
47
+ 'channel.send',
48
+ ]);
49
+ const CAPABILITY_NAME_SET = new Set(PLUGIN_CAPABILITY_NAMES);
50
+ /** Table-safe and consistent with how `defineCollection` guards collection names elsewhere in this workspace. */
51
+ const PACKAGE_NAME_PATTERN = /^(@[a-z0-9-]+\/)?[a-z0-9-]+$/;
52
+ const SEMVER_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
53
+ /** Deliberately loose: `^1.0.0`, `~1.2.3`, `>=1.0.0 <2.0.0`, or a bare `1.0.0`. */
54
+ const SEMVER_RANGE_PATTERN = /^[\^~]?\d+\.\d+\.\d+.*$/;
55
+ /** A real hostname shape — no wildcard, no scheme, no path. */
56
+ const HOSTNAME_PATTERN = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$/i;
57
+ /** The storage prefix a plugin's own capability grants — `plugins/<derived-name>`, scope stripped. */
58
+ function expectedStoragePrefix(pluginName) {
59
+ const derived = pluginName.includes('/')
60
+ ? (pluginName.split('/').at(-1) ?? pluginName)
61
+ : pluginName;
62
+ return `plugins/${derived}`;
63
+ }
64
+ function isWithinOwnPrefix(path, prefix) {
65
+ return path === prefix || path.startsWith(`${prefix}/`);
66
+ }
67
+ function checkCapability(raw, index, pluginName, issues) {
68
+ const path = `capabilities[${index}]`;
69
+ const separatorIndex = raw.indexOf(':');
70
+ const name = separatorIndex === -1 ? raw : raw.slice(0, separatorIndex);
71
+ const parameter = separatorIndex === -1 ? undefined : raw.slice(separatorIndex + 1);
72
+ if (!CAPABILITY_NAME_SET.has(name)) {
73
+ issues.push({ path, message: `unknown capability "${name}"` });
74
+ return;
75
+ }
76
+ const requiresParameter = PARAMETERIZED_CAPABILITIES.has(name);
77
+ if (!requiresParameter) {
78
+ if (parameter !== undefined) {
79
+ issues.push({ path, message: `"${name}" does not take a parameter, found "${raw}"` });
80
+ }
81
+ return;
82
+ }
83
+ if (parameter === undefined || parameter.trim() === '') {
84
+ issues.push({
85
+ path,
86
+ message: `"${name}" requires an explicit parameter, e.g. "${name}:example"`,
87
+ });
88
+ return;
89
+ }
90
+ if (name === 'http.fetch') {
91
+ if (parameter === '*') {
92
+ issues.push({ path, message: '"http.fetch" must name an explicit domain, never "*"' });
93
+ }
94
+ else if (!HOSTNAME_PATTERN.test(parameter)) {
95
+ issues.push({
96
+ path,
97
+ message: `"http.fetch" parameter "${parameter}" is not a valid hostname`,
98
+ });
99
+ }
100
+ return;
101
+ }
102
+ if (name === 'storage.read' || name === 'storage.write') {
103
+ const prefix = expectedStoragePrefix(pluginName);
104
+ if (!isWithinOwnPrefix(parameter, prefix)) {
105
+ issues.push({
106
+ path,
107
+ message: `"${name}" must stay within this plugin's own prefix ("${prefix}"), found "${parameter}"`,
108
+ });
109
+ }
110
+ return;
111
+ }
112
+ // `channel.send:<channel>` — channel names are a runtime registry
113
+ // (`@cogenta/channels`'s `createChannelRegistry`), not a fixed set this
114
+ // schema can enumerate; a non-empty parameter is already checked above.
115
+ }
116
+ function checkProvidesBlocks(blocks, issues) {
117
+ if (blocks === undefined)
118
+ return;
119
+ blocks.forEach((block, index) => {
120
+ const path = `provides.blocks[${index}]`;
121
+ if (typeof block.name !== 'string' || block.name.trim() === '') {
122
+ issues.push({ path: `${path}.name`, message: 'is required' });
123
+ }
124
+ if (typeof block.fallback !== 'string' || block.fallback.trim() === '') {
125
+ issues.push({
126
+ path: `${path}.fallback`,
127
+ message: 'is required — a block without a fallback is refused',
128
+ });
129
+ }
130
+ });
131
+ }
132
+ function collectIssues(input) {
133
+ const issues = [];
134
+ if (typeof input.name !== 'string' || !PACKAGE_NAME_PATTERN.test(input.name)) {
135
+ issues.push({
136
+ path: 'name',
137
+ message: 'must be a valid package name such as "@auteur/mon-plugin"',
138
+ });
139
+ }
140
+ if (typeof input.version !== 'string' || !SEMVER_PATTERN.test(input.version)) {
141
+ issues.push({ path: 'version', message: 'must be an exact semver version such as "1.0.0"' });
142
+ }
143
+ if (typeof input.engine !== 'string' || !SEMVER_RANGE_PATTERN.test(input.engine)) {
144
+ issues.push({ path: 'engine', message: 'must be a semver range such as "^1.0.0"' });
145
+ }
146
+ if (!PLUGIN_RUNTIMES.includes(input.runtime)) {
147
+ issues.push({ path: 'runtime', message: `must be one of: ${PLUGIN_RUNTIMES.join(', ')}` });
148
+ }
149
+ if (typeof input.isolated !== 'boolean') {
150
+ issues.push({ path: 'isolated', message: 'is required' });
151
+ }
152
+ if (!Array.isArray(input.capabilities)) {
153
+ issues.push({ path: 'capabilities', message: 'must be an array' });
154
+ }
155
+ else {
156
+ input.capabilities.forEach((capability, index) => {
157
+ if (typeof capability !== 'string' || capability.trim() === '') {
158
+ issues.push({ path: `capabilities[${index}]`, message: 'must be a non-empty string' });
159
+ return;
160
+ }
161
+ checkCapability(capability, index, input.name, issues);
162
+ });
163
+ }
164
+ if (input.provides === undefined || typeof input.provides !== 'object') {
165
+ issues.push({
166
+ path: 'provides',
167
+ message: 'is required (an empty object is a valid "provides nothing")',
168
+ });
169
+ }
170
+ else {
171
+ checkProvidesBlocks(input.provides.blocks, issues);
172
+ }
173
+ return issues;
174
+ }
175
+ /**
176
+ * Validates and freezes a plugin manifest. Every hard-refusal rule the lot
177
+ * specifies (`docs/lots/L7-extensibilite.md` § Manifeste) is enforced here:
178
+ * `http.fetch` without an explicit domain, a storage capability outside the
179
+ * plugin's own prefix, an unknown capability, and a block without a
180
+ * fallback are all refused with a single, complete error listing every
181
+ * issue at once — never a partial refusal an author has to rediscover one
182
+ * `definePlugin` call at a time.
183
+ */
184
+ export function definePlugin(input) {
185
+ const issues = collectIssues(input);
186
+ if (issues.length > 0) {
187
+ const lines = issues.map((issue) => ` ${issue.path}: ${issue.message}`).join('\n');
188
+ throw new CogentaError({
189
+ code: 'PLUGIN_MANIFEST_INVALID',
190
+ message: `Plugin manifest "${input.name ?? '(unnamed)'}" is not valid:\n${lines}`,
191
+ hint: 'Fix the fields listed above and try again.',
192
+ details: { name: input.name, issues },
193
+ });
194
+ }
195
+ return Object.freeze(input);
196
+ }
197
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { type PluginCapabilityName } from '../manifest.js';
2
+ /** How much trust a capability asks for — drives the extra-confirmation gate. */
3
+ export type PluginCapabilityRisk = 'low' | 'medium' | 'high';
4
+ export interface PluginCapabilityDescription {
5
+ /** Plain-language French, never a raw identifier fragment. */
6
+ readonly sentence: string;
7
+ readonly riskLevel: PluginCapabilityRisk;
8
+ readonly category: string;
9
+ }
10
+ /**
11
+ * Translates one exact capability string (e.g. `http.fetch:api.exemple.com`)
12
+ * into a plain-language description — never the raw `content.write_draft`
13
+ * shape, only what it means. Throws on a capability outside the known
14
+ * vocabulary rather than guessing a description for it: an untranslatable
15
+ * capability is a manifest-validation bug (`../manifest.js` already refuses
16
+ * it at `definePlugin` time), never something this function should paper
17
+ * over with a generic sentence.
18
+ */
19
+ export declare function describeCapability(capability: string): PluginCapabilityDescription;
20
+ /** Every capability name this module can describe — used by `describeCapability`'s own exhaustiveness test. */
21
+ export declare const DESCRIBABLE_CAPABILITY_NAMES: readonly PluginCapabilityName[];
22
+ //# sourceMappingURL=describe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describe.d.ts","sourceRoot":"","sources":["../../src/permissions/describe.ts"],"names":[],"mappings":"AACA,OAAO,EAA2B,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAEnF,iFAAiF;AACjF,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;AAE5D,MAAM,WAAW,2BAA2B;IAC1C,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,oBAAoB,CAAA;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AA0ID;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,2BAA2B,CAiBlF;AAED,+GAA+G;AAC/G,eAAO,MAAM,4BAA4B,EAAE,SAAS,oBAAoB,EAA4B,CAAA"}
@@ -0,0 +1,158 @@
1
+ import { CogentaError } from '@cogenta/core';
2
+ import { PLUGIN_CAPABILITY_NAMES } from '../manifest.js';
3
+ /**
4
+ * "Écran de permissions en langage clair" (docs/lots/L7-extensibilite.md,
5
+ * task 7). One real sentence and risk judgment per name in the frozen
6
+ * vocabulary (`../manifest.js`'s `PLUGIN_CAPABILITY_NAMES`) — no generic
7
+ * fallback, because a fallback ("ce plugin demande une permission
8
+ * technique") is exactly the kind of raw-identifier-adjacent non-answer the
9
+ * acceptance criterion ("aucun identifiant technique brut") exists to rule
10
+ * out. Risk is a real per-capability judgment, not a formula: destructive or
11
+ * bypass-review actions (publish, delete, site-wide config write, deploy,
12
+ * agent delegation, memory write) are `high`; actions confined to the
13
+ * plugin's own narrow surface or requiring a further human step (draft
14
+ * writes, dependency patches, storage within one's own prefix) are `medium`
15
+ * or `low` depending on blast radius.
16
+ */
17
+ const DESCRIPTIONS = {
18
+ 'content.read': {
19
+ sentence: 'Ce plugin pourra lire le contenu du site.',
20
+ riskLevel: 'low',
21
+ category: 'Contenu',
22
+ },
23
+ 'content.write_draft': {
24
+ sentence: 'Ce plugin pourra créer et modifier des brouillons, mais pas publier.',
25
+ riskLevel: 'low',
26
+ category: 'Contenu',
27
+ },
28
+ 'content.publish': {
29
+ sentence: 'Ce plugin pourra publier du contenu directement, sans validation humaine préalable.',
30
+ riskLevel: 'high',
31
+ category: 'Contenu',
32
+ },
33
+ 'content.delete': {
34
+ sentence: 'Ce plugin pourra supprimer du contenu du site.',
35
+ riskLevel: 'high',
36
+ category: 'Contenu',
37
+ },
38
+ 'media.read': {
39
+ sentence: 'Ce plugin pourra consulter les images et fichiers du site.',
40
+ riskLevel: 'low',
41
+ category: 'Médias',
42
+ },
43
+ 'media.write': {
44
+ sentence: 'Ce plugin pourra ajouter ou modifier des images et fichiers.',
45
+ riskLevel: 'medium',
46
+ category: 'Médias',
47
+ },
48
+ 'schema.read': {
49
+ sentence: 'Ce plugin pourra consulter la structure du contenu (les types de contenu et leurs champs).',
50
+ riskLevel: 'low',
51
+ category: 'Structure',
52
+ },
53
+ 'site.config_read': {
54
+ sentence: 'Ce plugin pourra consulter les réglages du site.',
55
+ riskLevel: 'low',
56
+ category: 'Réglages',
57
+ },
58
+ 'site.config_write': {
59
+ sentence: 'Ce plugin pourra modifier les réglages du site.',
60
+ riskLevel: 'high',
61
+ category: 'Réglages',
62
+ },
63
+ 'deps.scan': {
64
+ sentence: 'Ce plugin pourra analyser les dépendances du site à la recherche de failles connues.',
65
+ riskLevel: 'low',
66
+ category: 'Maintenance',
67
+ },
68
+ 'deps.patch': {
69
+ sentence: 'Ce plugin pourra proposer des corrections de dépendances, sous forme de suggestion à valider.',
70
+ riskLevel: 'medium',
71
+ category: 'Maintenance',
72
+ },
73
+ 'build.trigger': {
74
+ sentence: 'Ce plugin pourra déclencher une reconstruction du site.',
75
+ riskLevel: 'medium',
76
+ category: 'Maintenance',
77
+ },
78
+ 'deploy.trigger': {
79
+ sentence: 'Ce plugin pourra déclencher une mise en ligne du site.',
80
+ riskLevel: 'high',
81
+ category: 'Maintenance',
82
+ },
83
+ 'http.fetch': {
84
+ sentence: 'Ce plugin pourra envoyer des données à {param}.',
85
+ riskLevel: 'medium',
86
+ category: 'Réseau',
87
+ },
88
+ 'storage.read': {
89
+ sentence: 'Ce plugin pourra lire les fichiers qu’il a lui-même stockés.',
90
+ riskLevel: 'low',
91
+ category: 'Stockage',
92
+ },
93
+ 'storage.write': {
94
+ sentence: 'Ce plugin pourra créer ou modifier les fichiers qu’il stocke pour son propre usage.',
95
+ riskLevel: 'medium',
96
+ category: 'Stockage',
97
+ },
98
+ 'channel.send': {
99
+ sentence: 'Ce plugin pourra envoyer des messages sur le canal {param} (par exemple Telegram ou Slack).',
100
+ riskLevel: 'medium',
101
+ category: 'Canaux',
102
+ },
103
+ 'agent.delegate': {
104
+ sentence: 'Ce plugin pourra déléguer des tâches à un agent du site.',
105
+ riskLevel: 'high',
106
+ category: 'Agents',
107
+ },
108
+ 'memory.read': {
109
+ sentence: 'Ce plugin pourra consulter la mémoire des agents (leurs notes et apprentissages).',
110
+ riskLevel: 'medium',
111
+ category: 'Agents',
112
+ },
113
+ 'memory.write': {
114
+ sentence: 'Ce plugin pourra modifier la mémoire des agents (leurs notes et apprentissages).',
115
+ riskLevel: 'high',
116
+ category: 'Agents',
117
+ },
118
+ };
119
+ /**
120
+ * Splits `name` and an optional colon-suffixed parameter the same way
121
+ * `../manifest.js`'s `checkCapability` does, without re-importing its
122
+ * private helpers.
123
+ */
124
+ function splitCapability(capability) {
125
+ const separatorIndex = capability.indexOf(':');
126
+ return separatorIndex === -1
127
+ ? { name: capability, parameter: undefined }
128
+ : { name: capability.slice(0, separatorIndex), parameter: capability.slice(separatorIndex + 1) };
129
+ }
130
+ /**
131
+ * Translates one exact capability string (e.g. `http.fetch:api.exemple.com`)
132
+ * into a plain-language description — never the raw `content.write_draft`
133
+ * shape, only what it means. Throws on a capability outside the known
134
+ * vocabulary rather than guessing a description for it: an untranslatable
135
+ * capability is a manifest-validation bug (`../manifest.js` already refuses
136
+ * it at `definePlugin` time), never something this function should paper
137
+ * over with a generic sentence.
138
+ */
139
+ export function describeCapability(capability) {
140
+ const { name, parameter } = splitCapability(capability);
141
+ const entry = DESCRIPTIONS[name];
142
+ if (entry === undefined) {
143
+ throw new CogentaError({
144
+ code: 'PLUGIN_CAPABILITY_REFUSED',
145
+ message: `No plain-language description exists for capability "${capability}".`,
146
+ hint: 'This capability is outside the known vocabulary (PLUGIN_CAPABILITY_NAMES) — it should have been refused at definePlugin time.',
147
+ details: { capability },
148
+ });
149
+ }
150
+ return {
151
+ sentence: parameter === undefined ? entry.sentence : entry.sentence.replace('{param}', parameter),
152
+ riskLevel: entry.riskLevel,
153
+ category: entry.category,
154
+ };
155
+ }
156
+ /** Every capability name this module can describe — used by `describeCapability`'s own exhaustiveness test. */
157
+ export const DESCRIBABLE_CAPABILITY_NAMES = PLUGIN_CAPABILITY_NAMES;
158
+ //# sourceMappingURL=describe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describe.js","sourceRoot":"","sources":["../../src/permissions/describe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { type DatabaseHandle } from '@cogenta/core';
2
+ /** Why a plugin was killed and disabled — the two real policy violations this task enforces, plus a catch-all for any other worker crash. */
3
+ export type PluginViolationReason = 'timeout' | 'memory' | 'crash';
4
+ export interface PluginDisabledRecord {
5
+ readonly pluginName: string;
6
+ readonly reason: PluginViolationReason;
7
+ readonly details: string | null;
8
+ readonly disabledAt: string;
9
+ }
10
+ export interface PluginDisableStore {
11
+ /**
12
+ * "Tué et désactivé" — a plugin that exceeds its time or memory limit does
13
+ * not just have that one run terminated, it stops being runnable at all
14
+ * until a human re-enables it. Idempotent: disabling an already-disabled
15
+ * plugin overwrites the record with the newest violation, it does not
16
+ * error or accumulate history.
17
+ */
18
+ disable(pluginName: string, reason: PluginViolationReason, details?: string): Promise<void>;
19
+ /** A human decided the plugin is safe to run again. */
20
+ enable(pluginName: string): Promise<void>;
21
+ /** The real gate `runPlugin` checks before ever spawning a worker. */
22
+ isDisabled(pluginName: string): Promise<PluginDisabledRecord | null>;
23
+ }
24
+ export declare function createPluginDisableStore(db: DatabaseHandle, now?: () => number): PluginDisableStore;
25
+ //# sourceMappingURL=disabled.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disabled.d.ts","sourceRoot":"","sources":["../../src/permissions/disabled.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAmB,MAAM,eAAe,CAAA;AAGpE,6IAA6I;AAC7I,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAA;AAElE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAA;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;;;OAMG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE3F,uDAAuD;IACvD,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEzC,sEAAsE;IACtE,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAA;CACrE;AASD,wBAAgB,wBAAwB,CACtC,EAAE,EAAE,cAAc,EAClB,GAAG,GAAE,MAAM,MAAiB,GAC3B,kBAAkB,CA6BpB"}
@@ -0,0 +1,29 @@
1
+ import { identifier, sql } from '@cogenta/core';
2
+ import { PERMISSION_TABLES } from './tables.js';
3
+ export function createPluginDisableStore(db, now = Date.now) {
4
+ const disabled = identifier(PERMISSION_TABLES.disabled, db.dialect);
5
+ return {
6
+ async disable(pluginName, reason, details) {
7
+ await db.query(sql `delete from ${disabled} where plugin_name = ${pluginName}`);
8
+ await db.query(sql `
9
+ insert into ${disabled} (plugin_name, reason, details, disabled_at)
10
+ values (${pluginName}, ${reason}, ${details ?? null}, ${new Date(now()).toISOString()})`);
11
+ },
12
+ async enable(pluginName) {
13
+ await db.query(sql `delete from ${disabled} where plugin_name = ${pluginName}`);
14
+ },
15
+ async isDisabled(pluginName) {
16
+ const result = await db.query(sql `select * from ${disabled} where plugin_name = ${pluginName}`);
17
+ const row = result.rows[0];
18
+ if (row === undefined)
19
+ return null;
20
+ return {
21
+ pluginName: row.plugin_name,
22
+ reason: row.reason,
23
+ details: row.details,
24
+ disabledAt: row.disabled_at,
25
+ };
26
+ },
27
+ };
28
+ }
29
+ //# sourceMappingURL=disabled.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disabled.js","sourceRoot":"","sources":["../../src/permissions/disabled.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,UAAU,EAAE,GAAG,EAAE,MAAM,eAAe,CAAA;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAoC/C,MAAM,UAAU,wBAAwB,CACtC,EAAkB,EAClB,GAAG,GAAiB,IAAI,CAAC,GAAG;IAE5B,MAAM,QAAQ,GAAG,UAAU,CAAC,iBAAiB,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,CAAA;IAEnE,OAAO;QACL,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO;YACvC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAA,eAAe,QAAQ,wBAAwB,UAAU,EAAE,CAAC,CAAA;YAC9E,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAA;sBACF,QAAQ;kBACZ,UAAU,KAAK,MAAM,KAAK,OAAO,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAA;QAC7F,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,UAAU;YACrB,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAA,eAAe,QAAQ,wBAAwB,UAAU,EAAE,CAAC,CAAA;QAChF,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,UAAU;YACzB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,KAAK,CAC3B,GAAG,CAAA,iBAAiB,QAAQ,wBAAwB,UAAU,EAAE,CACjE,CAAA;YACD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YAC1B,IAAI,GAAG,KAAK,SAAS;gBAAE,OAAO,IAAI,CAAA;YAClC,OAAO;gBACL,UAAU,EAAE,GAAG,CAAC,WAAW;gBAC3B,MAAM,EAAE,GAAG,CAAC,MAA+B;gBAC3C,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,UAAU,EAAE,GAAG,CAAC,WAAW;aAC5B,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { type DatabaseHandle } from '@cogenta/core';
2
+ /** One user-approved capability for one plugin, keyed to the exact capability string. */
3
+ export interface PluginGrant {
4
+ readonly pluginName: string;
5
+ readonly capability: string;
6
+ readonly grantedAt: string;
7
+ }
8
+ export interface PluginGrantStore {
9
+ /**
10
+ * Records that `capability` (the exact string, e.g. `http.fetch:api.exemple.com`)
11
+ * has been approved for `pluginName`. Not this task's job to decide WHO
12
+ * gets to call this or through what UI (task 7's permission screen) — this
13
+ * is the real, minimal data-layer primitive that screen will call.
14
+ */
15
+ grant(pluginName: string, capability: string): Promise<void>;
16
+ /** Revoking an already-unrevoked-or-nonexistent grant is not an error — it's already in the state being asked for. */
17
+ revoke(pluginName: string, capability: string): Promise<void>;
18
+ /** Every currently-active (non-revoked) grant for a plugin. */
19
+ listGrants(pluginName: string): Promise<readonly PluginGrant[]>;
20
+ }
21
+ export declare function createPluginGrantStore(db: DatabaseHandle, now?: () => number): PluginGrantStore;
22
+ //# sourceMappingURL=grants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grants.d.ts","sourceRoot":"","sources":["../../src/permissions/grants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAA0B,MAAM,eAAe,CAAA;AAG3E,yFAAyF;AACzF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE5D,sHAAsH;IACtH,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE7D,+DAA+D;IAC/D,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC,CAAA;CAChE;AAUD,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,cAAc,EAClB,GAAG,GAAE,MAAM,MAAiB,GAC3B,gBAAgB,CAgClB"}
@@ -0,0 +1,31 @@
1
+ import { identifier, newId, sql } from '@cogenta/core';
2
+ import { PERMISSION_TABLES } from './tables.js';
3
+ export function createPluginGrantStore(db, now = Date.now) {
4
+ const grants = identifier(PERMISSION_TABLES.grants, db.dialect);
5
+ return {
6
+ async grant(pluginName, capability) {
7
+ // Re-granting an already-active capability is idempotent, not a
8
+ // duplicate row — replace rather than accumulate revoked history for
9
+ // the same exact (plugin, capability) pair still active.
10
+ await db.query(sql `delete from ${grants} where plugin_name = ${pluginName} and capability = ${capability} and revoked_at is null`);
11
+ await db.query(sql `
12
+ insert into ${grants} (id, plugin_name, capability, granted_at, revoked_at)
13
+ values (${newId(now)}, ${pluginName}, ${capability}, ${new Date(now()).toISOString()}, ${null})`);
14
+ },
15
+ async revoke(pluginName, capability) {
16
+ await db.query(sql `
17
+ update ${grants} set revoked_at = ${new Date(now()).toISOString()}
18
+ where plugin_name = ${pluginName} and capability = ${capability} and revoked_at is null`);
19
+ },
20
+ async listGrants(pluginName) {
21
+ const result = await db.query(sql `
22
+ select * from ${grants} where plugin_name = ${pluginName} and revoked_at is null order by granted_at asc`);
23
+ return result.rows.map((row) => ({
24
+ pluginName: row.plugin_name,
25
+ capability: row.capability,
26
+ grantedAt: row.granted_at,
27
+ }));
28
+ },
29
+ };
30
+ }
31
+ //# sourceMappingURL=grants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grants.js","sourceRoot":"","sources":["../../src/permissions/grants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAA;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAiC/C,MAAM,UAAU,sBAAsB,CACpC,EAAkB,EAClB,GAAG,GAAiB,IAAI,CAAC,GAAG;IAE5B,MAAM,MAAM,GAAG,UAAU,CAAC,iBAAiB,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,CAAA;IAE/D,OAAO;QACL,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,UAAU;YAChC,gEAAgE;YAChE,qEAAqE;YACrE,yDAAyD;YACzD,MAAM,EAAE,CAAC,KAAK,CACZ,GAAG,CAAA,eAAe,MAAM,wBAAwB,UAAU,qBAAqB,UAAU,yBAAyB,CACnH,CAAA;YACD,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAA;sBACF,MAAM;kBACV,KAAK,CAAC,GAAG,CAAC,KAAK,UAAU,KAAK,UAAU,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,IAAI,GAAG,CAAC,CAAA;QACrG,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,UAAU;YACjC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAA;iBACP,MAAM,qBAAqB,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE;8BAC3C,UAAU,qBAAqB,UAAU,yBAAyB,CAAC,CAAA;QAC7F,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,UAAU;YACzB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,KAAK,CAAW,GAAG,CAAA;wBACzB,MAAM,wBAAwB,UAAU,iDAAiD,CAAC,CAAA;YAC5G,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBAC/B,UAAU,EAAE,GAAG,CAAC,WAAW;gBAC3B,UAAU,EAAE,GAAG,CAAC,UAAU;gBAC1B,SAAS,EAAE,GAAG,CAAC,UAAU;aAC1B,CAAC,CAAC,CAAA;QACL,CAAC;KACF,CAAA;AACH,CAAC"}