@fungi.computer/puffball 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/app-api.js CHANGED
@@ -4,13 +4,17 @@ import { isAppApiMethodName } from "./app-method-runtime.js";
4
4
  export { appApiReservedMethodNames } from "./app-method-runtime.js";
5
5
  /** Public method names, including grouped operations such as desktop.arrange. A name cannot also be a group (`files` with `files.read`). */
6
6
  export const appApiMethodNameSchema = Schema.String.check(Schema.makeFilter(isAppApiMethodName));
7
+ /** Distinguish containers only after the owning JSON decoder has succeeded. */
8
+ function isJsonContainer(value) {
9
+ return value !== null && typeof value === "object";
10
+ }
7
11
  function withinDepth(value, depth = 0) {
8
12
  if (depth > 16)
9
13
  return false;
10
- if (Schema.is(Schema.Array(Schema.Json))(value))
11
- return value.every((child) => withinDepth(child, depth + 1));
12
- if (Schema.is(Schema.JsonObject)(value))
13
- return Object.values(value).every((child) => withinDepth(child, depth + 1));
14
+ if (isJsonContainer(value))
15
+ for (const child of Object.values(value))
16
+ if (!withinDepth(child, depth + 1))
17
+ return false;
14
18
  return true;
15
19
  }
16
20
  /** JSON Schema projections are data, bounded before a renderer or compiler reads them. */
@@ -23,16 +27,12 @@ const method = Schema.Struct({
23
27
  output: projection,
24
28
  pending: Schema.optional(Schema.Literal(true)),
25
29
  hidden: Schema.optional(Schema.Literal(true)),
26
- anonymous: Schema.optional(Schema.Literal(true)),
27
30
  present: Schema.optional(Schema.Struct({
28
31
  verb: Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(32)),
29
32
  })),
30
33
  effect: Schema.Literals(["read", "write", "external"]),
31
34
  requires: Schema.Array(Schema.Literals(appCapabilityIds)).pipe(Schema.check(Schema.makeFilter((values) => new Set(values).size === values.length))),
32
- }).check(Schema.makeFilter((value) => value.anonymous !== true ||
33
- (value.effect === "read" && value.requires.length === 0), {
34
- message: "Anonymous methods must be reads with no required capabilities",
35
- }));
35
+ });
36
36
  /** The build-generated, digest-covered method and event catalog; it grants no authority. */
37
37
  export const appApiSchema = Schema.Struct({
38
38
  methods: Schema.Record(Schema.String, method).pipe(Schema.check(Schema.makeFilter((methods) => Object.keys(methods).every(Schema.is(appApiMethodNameSchema)), { message: "Invalid App API method name" })), Schema.check(Schema.makeFilter((methods) => Object.keys(methods).length <= 64)), Schema.check(Schema.makeFilter((methods) => {
@@ -133,6 +133,11 @@ export declare const appBackendBindingKinds: {
133
133
  readonly requires: readonly ["workflow.run", "workflow.arm"];
134
134
  readonly effect: "write";
135
135
  };
136
+ readonly pauseSchedule: {
137
+ readonly cap: "app.workflow.run";
138
+ readonly requires: readonly ["workflow.run", "workflow.arm"];
139
+ readonly effect: "write";
140
+ };
136
141
  readonly schedules: {
137
142
  readonly cap: "app.workflow.read";
138
143
  readonly requires: readonly ["workflow.run"];
@@ -291,6 +296,21 @@ export declare const appBackendBindingKinds: {
291
296
  readonly requires: readonly ["agent.send"];
292
297
  readonly effect: "write";
293
298
  };
299
+ readonly schedules: {
300
+ readonly cap: "agent.read";
301
+ readonly requires: readonly ["agent.read"];
302
+ readonly effect: "read";
303
+ };
304
+ readonly pauseSchedule: {
305
+ readonly cap: "agent.manage";
306
+ readonly requires: readonly ["agent.manage"];
307
+ readonly effect: "write";
308
+ };
309
+ readonly deleteSchedule: {
310
+ readonly cap: "agent.manage";
311
+ readonly requires: readonly ["agent.manage"];
312
+ readonly effect: "write";
313
+ };
294
314
  };
295
315
  };
296
316
  };
@@ -122,6 +122,11 @@ export const appBackendBindingKinds = {
122
122
  requires: ["workflow.run", "workflow.arm"],
123
123
  effect: "write",
124
124
  },
125
+ pauseSchedule: {
126
+ cap: "app.workflow.run",
127
+ requires: ["workflow.run", "workflow.arm"],
128
+ effect: "write",
129
+ },
125
130
  schedules: {
126
131
  cap: "app.workflow.read",
127
132
  requires: ["workflow.run"],
@@ -264,6 +269,21 @@ export const appBackendBindingKinds = {
264
269
  operations: {
265
270
  list: { cap: "agent.list", requires: ["agent.list"], effect: "read" },
266
271
  send: { cap: "agent.send", requires: ["agent.send"], effect: "write" },
272
+ schedules: {
273
+ cap: "agent.read",
274
+ requires: ["agent.read"],
275
+ effect: "read",
276
+ },
277
+ pauseSchedule: {
278
+ cap: "agent.manage",
279
+ requires: ["agent.manage"],
280
+ effect: "write",
281
+ },
282
+ deleteSchedule: {
283
+ cap: "agent.manage",
284
+ requires: ["agent.manage"],
285
+ effect: "write",
286
+ },
267
287
  },
268
288
  },
269
289
  };
@@ -11,7 +11,7 @@ export declare const appBackendShardBindingsSchema: Schema.$Array<Schema.Union<S
11
11
  readonly name: Schema.Literal<"BACKGROUND" | "GIT" | "EVENTS" | "APPS" | "WORKFLOWS" | "APP_STORAGE" | "MEDIA" | "COMPUTER" | "INBOX" | "AGENTS">;
12
12
  readonly operations: Schema.$Array<Schema.Union<Schema.Struct<{
13
13
  readonly name: Schema.Literal<string>;
14
- readonly cap: Schema.Literal<"agent.list" | "agent.send" | "app.events.emit" | "app.background.admit" | "app.git.create" | "app.git.fork" | "app.git.read" | "app.git.write" | "app.git.exchange" | "app.register" | "app.catalog.read" | "app.build" | "app.select" | "app.fork" | "app.workflow.read" | "app.workflow.run" | "app.storage.read" | "app.storage.write" | "app.media.read" | "app.media.generate" | "app.computer.read" | "app.computer.write" | "app.computer.exec" | "inbox.read" | "inbox.visit">;
14
+ readonly cap: Schema.Literal<"agent.list" | "agent.manage" | "agent.read" | "agent.send" | "app.events.emit" | "app.background.admit" | "app.git.create" | "app.git.fork" | "app.git.read" | "app.git.write" | "app.git.exchange" | "app.register" | "app.catalog.read" | "app.build" | "app.select" | "app.fork" | "app.workflow.read" | "app.workflow.run" | "app.storage.read" | "app.storage.write" | "app.media.read" | "app.media.generate" | "app.computer.read" | "app.computer.write" | "app.computer.exec" | "inbox.read" | "inbox.visit">;
15
15
  }>[]>>;
16
16
  }>[]>>;
17
17
  /** Look up an operation within its declared kind; unknown names have no authority. */
@@ -64,20 +64,41 @@ export type AppCapabilityId = (typeof appCapabilityIds)[number];
64
64
  /** Backend requests are narrower than the App capabilities a Team approves. */
65
65
  export type { AppBackendBinding } from "./app-backend-binding-vocabulary.js";
66
66
  import type { AppBackendBinding } from "./app-backend-binding-vocabulary.js";
67
+ /**
68
+ * Effect-free DTO projection of the owning JSON schema; equality is tested.
69
+ * Workers RPC's Serializable mapping unfolds anonymous inline recursion.
70
+ * A named array branch bounds it without expanding an inline array,
71
+ * without importing Effect into this declaration graph.
72
+ * @inline
73
+ */
74
+ export type AppApiJsonValue = null | boolean | number | string | AppApiJsonArray | AppApiJsonObject;
75
+ /**
76
+ * Named recursive array branch required by the Workers RPC type mapper.
77
+ * @inline
78
+ */
79
+ export type AppApiJsonArray = {
80
+ readonly [index: number]: AppApiJsonValue;
81
+ readonly length: number;
82
+ };
83
+ /**
84
+ * Package-internal declaration name; the public root exports AppApi.
85
+ * @inline
86
+ */
87
+ export type AppApiJsonObject = {
88
+ readonly [key: string]: AppApiJsonValue;
89
+ };
67
90
  /** Build-generated method and event metadata. This data-only projection grants no authority. */
68
91
  export type AppApi = Readonly<{
69
92
  methods: Readonly<Record<string, Readonly<{
70
93
  description: string;
71
- input: object;
72
- output: object;
94
+ input: AppApiJsonObject;
95
+ output: AppApiJsonObject;
73
96
  effect: "read" | "write" | "external";
74
97
  requires: readonly AppCapabilityId[];
75
98
  /** This method may return Agar's shared Pending result while working. */
76
99
  pending?: true | undefined;
77
100
  /** Omit from Workflow and tool discovery, without changing direct-call authority. */
78
101
  hidden?: true | undefined;
79
- /** Request anonymous read admission; declaration alone grants no authority. */
80
- anonymous?: true | undefined;
81
102
  /** Finished calls read as a person-facing row projected by the App's hidden `present` method. */
82
103
  present?: Readonly<{
83
104
  verb: string;
@@ -92,7 +113,7 @@ export type AppApi = Readonly<{
92
113
  /** Declared event payload schemas; hosts validate emits against the selected Release. */
93
114
  events?: Readonly<Record<string, Readonly<{
94
115
  description: string;
95
- payload: object;
116
+ payload: AppApiJsonObject;
96
117
  }>>>;
97
118
  }>;
98
119
  /** Navigation requests an App can handle for the shell. */
@@ -1461,13 +1461,12 @@ export declare const decodeReleaseLifecycleStoreResult: (input: unknown, options
1461
1461
  api?: Readonly<{
1462
1462
  methods: Readonly<Record<string, Readonly<{
1463
1463
  description: string;
1464
- input: object;
1465
- output: object;
1464
+ input: import("../app-vocabulary.js").AppApiJsonObject;
1465
+ output: import("../app-vocabulary.js").AppApiJsonObject;
1466
1466
  effect: "read" | "write" | "external";
1467
1467
  requires: readonly import("../app-vocabulary.js").AppCapabilityId[];
1468
1468
  pending?: true | undefined;
1469
1469
  hidden?: true | undefined;
1470
- anonymous?: true | undefined;
1471
1470
  present?: Readonly<{
1472
1471
  verb: string;
1473
1472
  }> | undefined;
@@ -1479,7 +1478,7 @@ export declare const decodeReleaseLifecycleStoreResult: (input: unknown, options
1479
1478
  }>;
1480
1479
  events?: Readonly<Record<string, Readonly<{
1481
1480
  description: string;
1482
- payload: object;
1481
+ payload: import("../app-vocabulary.js").AppApiJsonObject;
1483
1482
  }>>>;
1484
1483
  }>;
1485
1484
  displayName?: string | undefined;
@@ -1518,7 +1517,9 @@ export declare const decodeReleaseLifecycleStoreResult: (input: unknown, options
1518
1517
  help?: Readonly<{
1519
1518
  order?: number | undefined;
1520
1519
  }> | undefined;
1521
- menu?: Readonly<{
1520
+ menu
1521
+ /** Canonical Effect Schema for a verified immutable artifact snapshot. */
1522
+ ?: Readonly<{
1522
1523
  order?: number | undefined;
1523
1524
  }> | undefined;
1524
1525
  palette?: Readonly<{
@@ -219,13 +219,12 @@ export declare const decodePublicWebsiteAuthorityStoreResult: (input: unknown, o
219
219
  api?: Readonly<{
220
220
  methods: Readonly<Record<string, Readonly<{
221
221
  description: string;
222
- input: object;
223
- output: object;
222
+ input: import("../app-vocabulary.js").AppApiJsonObject;
223
+ output: import("../app-vocabulary.js").AppApiJsonObject;
224
224
  effect: "read" | "write" | "external";
225
225
  requires: readonly import("../app-vocabulary.js").AppCapabilityId[];
226
226
  pending?: true | undefined;
227
227
  hidden?: true | undefined;
228
- anonymous?: true | undefined;
229
228
  present?: Readonly<{
230
229
  verb: string;
231
230
  }> | undefined;
@@ -237,7 +236,7 @@ export declare const decodePublicWebsiteAuthorityStoreResult: (input: unknown, o
237
236
  }>;
238
237
  events?: Readonly<Record<string, Readonly<{
239
238
  description: string;
240
- payload: object;
239
+ payload: import("../app-vocabulary.js").AppApiJsonObject;
241
240
  }>>>;
242
241
  }>;
243
242
  displayName?: string | undefined;
@@ -175,6 +175,10 @@ The runtime-neutral registry shared by declarations, admission and Exec.
175
175
  | `WORKFLOWS.operations.disarmSchedule.cap` | `"app.workflow.run"` | `"app.workflow.run"` | - |
176
176
  | `WORKFLOWS.operations.disarmSchedule.requires` | readonly \[`"workflow.run"`, `"workflow.arm"`\] | - | - |
177
177
  | `WORKFLOWS.operations.disarmSchedule.effect` | `"write"` | `"write"` | - |
178
+ | `WORKFLOWS.operations.pauseSchedule` | `object` | - | - |
179
+ | `WORKFLOWS.operations.pauseSchedule.cap` | `"app.workflow.run"` | `"app.workflow.run"` | - |
180
+ | `WORKFLOWS.operations.pauseSchedule.requires` | readonly \[`"workflow.run"`, `"workflow.arm"`\] | - | - |
181
+ | `WORKFLOWS.operations.pauseSchedule.effect` | `"write"` | `"write"` | - |
178
182
  | `WORKFLOWS.operations.schedules` | `object` | - | - |
179
183
  | `WORKFLOWS.operations.schedules.cap` | `"app.workflow.read"` | `"app.workflow.read"` | - |
180
184
  | `WORKFLOWS.operations.schedules.requires` | readonly \[`"workflow.run"`\] | - | - |
@@ -294,3 +298,15 @@ The runtime-neutral registry shared by declarations, admission and Exec.
294
298
  | `AGENTS.operations.send.cap` | `"agent.send"` | `"agent.send"` | - |
295
299
  | `AGENTS.operations.send.requires` | readonly \[`"agent.send"`\] | - | - |
296
300
  | `AGENTS.operations.send.effect` | `"write"` | `"write"` | - |
301
+ | `AGENTS.operations.schedules` | `object` | - | - |
302
+ | `AGENTS.operations.schedules.cap` | `"agent.read"` | `"agent.read"` | - |
303
+ | `AGENTS.operations.schedules.requires` | readonly \[`"agent.read"`\] | - | - |
304
+ | `AGENTS.operations.schedules.effect` | `"read"` | `"read"` | - |
305
+ | `AGENTS.operations.pauseSchedule` | `object` | - | - |
306
+ | `AGENTS.operations.pauseSchedule.cap` | `"agent.manage"` | `"agent.manage"` | - |
307
+ | `AGENTS.operations.pauseSchedule.requires` | readonly \[`"agent.manage"`\] | - | - |
308
+ | `AGENTS.operations.pauseSchedule.effect` | `"write"` | `"write"` | - |
309
+ | `AGENTS.operations.deleteSchedule` | `object` | - | - |
310
+ | `AGENTS.operations.deleteSchedule.cap` | `"agent.manage"` | `"agent.manage"` | - |
311
+ | `AGENTS.operations.deleteSchedule.requires` | readonly \[`"agent.manage"`\] | - | - |
312
+ | `AGENTS.operations.deleteSchedule.effect` | `"write"` | `"write"` | - |
@@ -102,11 +102,11 @@ ceiling.
102
102
 
103
103
  #### Parameters
104
104
 
105
- | Parameter | Type |
106
- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
107
- | `operation` | [`AppBackendBindingOperation`](app-backend-binding-vocabulary.md#appbackendbindingoperation) |
108
- | `method` | \| `Pick`\<`Readonly`\<\{ `description`: `string`; `input`: `object`; `output`: `object`; `effect`: `"write"` \| `"external"` \| `"read"`; `requires`: readonly ( \| `"approvals"` \| `"agent.list"` \| `"agent.manage"` \| `"agent.rename"` \| `"agent.avatar"` \| `"agent.toolPolicy"` \| `"agent.read"` \| `"agent.send"` \| `"computer.list"` \| `"computer.readFile"` \| `"computer.writeFile"` \| `"computer.execute"` \| `"llm.generation"` \| `"media.generation"` \| `"games:servers"` \| `"git.repository"` \| `"apps.open"` \| `"apps.call"` \| `"app.storage"` \| `"app.events.emit"` \| `"team.workbenchHost"` \| `"marketplace.browse"` \| `"marketplace.purchase"` \| `"workflow.run"` \| `"workflow.publish"` \| `"workflow.arm"` \| `"world"` \| `"channels.read"` \| `"channels.personal.manage"`)[]; `pending?`: `true`; `hidden?`: `true`; `anonymous?`: `true`; `present?`: `Readonly`\<\{ `verb`: `string`; \}\>; \}\>, `"requires"` \| `"effect"`\> \| `undefined` |
109
- | `ceiling` | `"write"` \| `"read"` |
105
+ | Parameter | Type |
106
+ | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
107
+ | `operation` | [`AppBackendBindingOperation`](app-backend-binding-vocabulary.md#appbackendbindingoperation) |
108
+ | `method` | \| `Pick`\<`Readonly`\<\{ `description`: `string`; `input`: \{ \[`key`: `string`\]: \| `null` \| `string` \| `number` \| `false` \| `true` \| \{ \[`index`: `number`\]: AppApiJsonValue; `length`: `number`; \} \| AppApiJsonObject; \}; `output`: \{ \[`key`: `string`\]: \| `null` \| `string` \| `number` \| `false` \| `true` \| \{ \[`index`: `number`\]: AppApiJsonValue; `length`: `number`; \} \| AppApiJsonObject; \}; `effect`: `"write"` \| `"external"` \| `"read"`; `requires`: readonly ( \| `"approvals"` \| `"agent.list"` \| `"agent.manage"` \| `"agent.rename"` \| `"agent.avatar"` \| `"agent.toolPolicy"` \| `"agent.read"` \| `"agent.send"` \| `"computer.list"` \| `"computer.readFile"` \| `"computer.writeFile"` \| `"computer.execute"` \| `"llm.generation"` \| `"media.generation"` \| `"games:servers"` \| `"git.repository"` \| `"apps.open"` \| `"apps.call"` \| `"app.storage"` \| `"app.events.emit"` \| `"team.workbenchHost"` \| `"marketplace.browse"` \| `"marketplace.purchase"` \| `"workflow.run"` \| `"workflow.publish"` \| `"workflow.arm"` \| `"world"` \| `"channels.read"` \| `"channels.personal.manage"`)[]; `pending?`: `true`; `hidden?`: `true`; `present?`: `Readonly`\<\{ `verb`: `string`; \}\>; \}\>, `"requires"` \| `"effect"`\> \| `undefined` |
109
+ | `ceiling` | `"write"` \| `"read"` |
110
110
 
111
111
  #### Returns
112
112
 
package/docs/api/index.md CHANGED
@@ -739,13 +739,40 @@ type AppApi = Readonly<{
739
739
  string,
740
740
  Readonly<{
741
741
  description: string;
742
- input: object;
743
- output: object;
742
+ input: {
743
+ [key: string]:
744
+ | null
745
+ | string
746
+ | number
747
+ | false
748
+ | true
749
+ | {
750
+ [index: number]: AppApiJsonValue;
751
+ length: number;
752
+ }
753
+ | {
754
+ [key: string]: AppApiJsonValue;
755
+ };
756
+ };
757
+ output: {
758
+ [key: string]:
759
+ | null
760
+ | string
761
+ | number
762
+ | false
763
+ | true
764
+ | {
765
+ [index: number]: AppApiJsonValue;
766
+ length: number;
767
+ }
768
+ | {
769
+ [key: string]: AppApiJsonValue;
770
+ };
771
+ };
744
772
  effect: "read" | "write" | "external";
745
773
  requires: readonly AppCapabilityId[];
746
774
  pending?: true;
747
775
  hidden?: true;
748
- anonymous?: true;
749
776
  present?: Readonly<{
750
777
  verb: string;
751
778
  }>;
@@ -762,7 +789,21 @@ type AppApi = Readonly<{
762
789
  string,
763
790
  Readonly<{
764
791
  description: string;
765
- payload: object;
792
+ payload: {
793
+ [key: string]:
794
+ | null
795
+ | string
796
+ | number
797
+ | false
798
+ | true
799
+ | {
800
+ [index: number]: AppApiJsonValue;
801
+ length: number;
802
+ }
803
+ | {
804
+ [key: string]: AppApiJsonValue;
805
+ };
806
+ };
766
807
  }>
767
808
  >
768
809
  >;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fungi.computer/puffball",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "author": "Levi <levi@technomancy.dev>",
5
5
  "description": "Immutable App/Release catalog with verified public website delivery",
6
6
  "type": "module",