@fungi.computer/puffball 0.0.1 → 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.
package/dist/app-api.js CHANGED
@@ -24,6 +24,9 @@ const method = Schema.Struct({
24
24
  pending: Schema.optional(Schema.Literal(true)),
25
25
  hidden: Schema.optional(Schema.Literal(true)),
26
26
  anonymous: Schema.optional(Schema.Literal(true)),
27
+ present: Schema.optional(Schema.Struct({
28
+ verb: Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(32)),
29
+ })),
27
30
  effect: Schema.Literals(["read", "write", "external"]),
28
31
  requires: Schema.Array(Schema.Literals(appCapabilityIds)).pipe(Schema.check(Schema.makeFilter((values) => new Set(values).size === values.length))),
29
32
  }).check(Schema.makeFilter((value) => value.anonymous !== true ||
@@ -65,17 +65,20 @@ export declare const appBackendBindingKinds: {
65
65
  readonly requires: readonly ["git.repository", "computer.execute"];
66
66
  readonly effect: "write";
67
67
  };
68
- /** Read one build job's current status; the host re-checks the caller is the owner. */
68
+ /** Read one build job's current status; the host re-checks the caller
69
+ * is the owner. An operation is granted only through approved
70
+ * capabilities, so it needs the ones its build was admitted with. */
69
71
  readonly buildStatus: {
70
72
  readonly cap: "app.build";
71
- readonly requires: readonly [];
73
+ readonly requires: readonly ["git.repository", "computer.execute"];
72
74
  readonly effect: "read";
73
75
  };
74
76
  /** Install a Release at an installation id, or switch a live one onto
75
- * it; the host re-checks the caller is the owner. */
77
+ * it; the host re-checks the caller is the owner. It completes the
78
+ * build-and-install loop, under the capabilities a build needs. */
76
79
  readonly select: {
77
80
  readonly cap: "app.select";
78
- readonly requires: readonly [];
81
+ readonly requires: readonly ["git.repository", "computer.execute"];
79
82
  readonly effect: "write";
80
83
  };
81
84
  readonly catalog: {
@@ -83,10 +86,11 @@ export declare const appBackendBindingKinds: {
83
86
  readonly requires: readonly ["team.workbenchHost"];
84
87
  readonly effect: "read";
85
88
  };
86
- /** Fork a platform App's published source into its own Team-owned App. */
89
+ /** Fork a platform App's published source into its own Team-owned App,
90
+ * as a repository in the calling installation's Git. */
87
91
  readonly fork: {
88
92
  readonly cap: "app.fork";
89
- readonly requires: readonly [];
93
+ readonly requires: readonly ["git.repository"];
90
94
  readonly effect: "write";
91
95
  };
92
96
  };
@@ -54,17 +54,20 @@ export const appBackendBindingKinds = {
54
54
  requires: ["git.repository", "computer.execute"],
55
55
  effect: "write",
56
56
  },
57
- /** Read one build job's current status; the host re-checks the caller is the owner. */
57
+ /** Read one build job's current status; the host re-checks the caller
58
+ * is the owner. An operation is granted only through approved
59
+ * capabilities, so it needs the ones its build was admitted with. */
58
60
  buildStatus: {
59
61
  cap: "app.build",
60
- requires: [],
62
+ requires: ["git.repository", "computer.execute"],
61
63
  effect: "read",
62
64
  },
63
65
  /** Install a Release at an installation id, or switch a live one onto
64
- * it; the host re-checks the caller is the owner. */
66
+ * it; the host re-checks the caller is the owner. It completes the
67
+ * build-and-install loop, under the capabilities a build needs. */
65
68
  select: {
66
69
  cap: "app.select",
67
- requires: [],
70
+ requires: ["git.repository", "computer.execute"],
68
71
  effect: "write",
69
72
  },
70
73
  catalog: {
@@ -72,10 +75,11 @@ export const appBackendBindingKinds = {
72
75
  requires: ["team.workbenchHost"],
73
76
  effect: "read",
74
77
  },
75
- /** Fork a platform App's published source into its own Team-owned App. */
78
+ /** Fork a platform App's published source into its own Team-owned App,
79
+ * as a repository in the calling installation's Git. */
76
80
  fork: {
77
81
  cap: "app.fork",
78
- requires: [],
82
+ requires: ["git.repository"],
79
83
  effect: "write",
80
84
  },
81
85
  },
@@ -1,7 +1,7 @@
1
1
  import * as Schema from "effect/Schema";
2
2
  import { type AppDeclaration, type AppDeclaredCommand } from "./app-vocabulary.js";
3
3
  export declare const appRoleSchema: Schema.Literals<readonly ["dashboard", "inbox", "files", "media", "sessions", "terminal"]>;
4
- export declare const appCapabilityIdSchema: Schema.Literals<readonly ["agent.list", "agent.manage", "agent.rename", "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"]>;
4
+ export declare const appCapabilityIdSchema: Schema.Literals<readonly ["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"]>;
5
5
  export declare const appHandlerSchema: Schema.Literals<readonly ["file.open"]>;
6
6
  /**
7
7
  * One declared command: a Whistle definition's identity and projections.
@@ -26,7 +26,7 @@ export declare const appEventFactSchema: z.ZodObject<{
26
26
  appId: z.ZodString;
27
27
  releaseId: z.ZodString;
28
28
  gitSource: z.ZodOptional<z.ZodObject<{
29
- eventId: z.ZodString;
29
+ eventId: z.ZodLazy<z.ZodString>;
30
30
  repository: z.ZodString;
31
31
  updates: z.ZodArray<z.ZodObject<{
32
32
  ref: z.ZodString;
@@ -52,10 +52,10 @@ export declare const appMethodCallerSchema: z.ZodMiniObject<{
52
52
  keyId: z.ZodMiniString<string>;
53
53
  }, z.core.$strip>], "kind">;
54
54
  backgroundLane: z.ZodMiniOptional<z.ZodMiniString<string>>;
55
- backgroundOrigin: z.ZodMiniOptional<z.ZodMiniObject<{
55
+ backgroundOrigin: z.ZodMiniOptional<z.ZodMiniLazy<z.ZodMiniObject<{
56
56
  method: z.ZodMiniString<string>;
57
57
  seal: z.ZodMiniString<string>;
58
- }, z.core.$strict>>;
58
+ }, z.core.$strict>>>;
59
59
  role: z.ZodMiniOptional<z.ZodMiniEnum<{
60
60
  member: "member";
61
61
  owner: "owner";
@@ -56,10 +56,10 @@ export const workflowAttestationSchema = z.object({
56
56
  });
57
57
  // Keep the single origin grammar in the lightweight caller module. The host-side
58
58
  // background-replay entry exposes this same schema without a runtime import cycle.
59
- const backgroundOrigin = z.strictObject({
59
+ const backgroundOrigin = z.lazy(() => z.strictObject({
60
60
  method: z.string().check(z.refine((name) => isAppApiMethodName(name))),
61
61
  seal: z.string().check(z.regex(/^[A-Za-z0-9_-]{43}$/u)),
62
- });
62
+ }));
63
63
  /** Sole grammar for the host-minted Computer pin and actor attribution. */
64
64
  export const appMethodCallerSchema = z.object({
65
65
  computerId: z.nullable(identity),
@@ -58,7 +58,7 @@ export declare function resolveAppRoles(choices: ReadonlyMap<AppRole, string>, c
58
58
  * Host capabilities an App may request. A request is never authority; the
59
59
  * Team's installation grants decide. Extend this list here.
60
60
  */
61
- export declare const appCapabilityIds: readonly ["agent.list", "agent.manage", "agent.rename", "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"];
61
+ export declare const appCapabilityIds: readonly ["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"];
62
62
  /** One requestable host capability id. */
63
63
  export type AppCapabilityId = (typeof appCapabilityIds)[number];
64
64
  /** Backend requests are narrower than the App capabilities a Team approves. */
@@ -78,6 +78,10 @@ export type AppApi = Readonly<{
78
78
  hidden?: true | undefined;
79
79
  /** Request anonymous read admission; declaration alone grants no authority. */
80
80
  anonymous?: true | undefined;
81
+ /** Finished calls read as a person-facing row projected by the App's hidden `present` method. */
82
+ present?: Readonly<{
83
+ verb: string;
84
+ }> | undefined;
81
85
  }>>>;
82
86
  /** A signed dynamic tool namespace; its methods remain subject to ordinary admission. */
83
87
  toolFamily?: Readonly<{
@@ -52,6 +52,7 @@ export const appCapabilityIds = [
52
52
  "agent.list",
53
53
  "agent.manage",
54
54
  "agent.rename",
55
+ "agent.avatar",
55
56
  "agent.toolPolicy",
56
57
  "agent.read",
57
58
  "agent.send",
@@ -4,19 +4,19 @@ import { type HostActor, type AppMethodCallContext } from "./app-method-runtime.
4
4
  import type { AppApi } from "./app-vocabulary.js";
5
5
  export { backgroundSyncAllowed } from "./internal/background-sync.js";
6
6
  /** The caller's single lightweight grammar for a host-sealed enqueue origin. */
7
- export declare const backgroundOriginSchema: import("zod/mini").ZodMiniObject<{
7
+ export declare const backgroundOriginSchema: import("zod/mini").ZodMiniLazy<import("zod/mini").ZodMiniObject<{
8
8
  method: import("zod/mini").ZodMiniString<string>;
9
9
  seal: import("zod/mini").ZodMiniString<string>;
10
- }, z.core.$strict>;
10
+ }, z.core.$strict>>;
11
11
  /** Origin evidence, never a retained grant or credential. */
12
12
  export type BackgroundOrigin = z.output<typeof backgroundOriginSchema>;
13
13
  /** The closed result of checking a claimed job's origin in a fresh replay frame. */
14
- export declare const claimedJobAdmissionSchema: z.ZodUnion<readonly [z.ZodObject<{
14
+ export declare const claimedJobAdmissionSchema: z.ZodLazy<z.ZodUnion<readonly [z.ZodObject<{
15
15
  kind: z.ZodLiteral<"admitted">;
16
16
  }, z.core.$strict>, z.ZodObject<{
17
17
  kind: z.ZodLiteral<"refused">;
18
18
  code: z.ZodLiteral<"access_changed">;
19
- }, z.core.$strict>]>;
19
+ }, z.core.$strict>]>>;
20
20
  /** A claim either passes origin admission or refuses before binding effects. */
21
21
  export type ClaimedJobAdmission = z.output<typeof claimedJobAdmissionSchema>;
22
22
  /** Host-minted replay port; an App cannot declare this binding. */
@@ -50,7 +50,7 @@ export declare function backgroundContext(context: AppMethodCallContext, ancestr
50
50
  /** App-side eligibility reads only the host-attested context; it never invents ancestry. */
51
51
  export declare function mayEnqueueBackground(context: AppMethodCallContext): boolean;
52
52
  /** Identity and observed revisions only. Unknown fields, including bearer material, refuse. */
53
- export declare const backgroundWakeSchema: z.ZodObject<{
53
+ export declare const backgroundWakeSchema: z.ZodLazy<z.ZodObject<{
54
54
  installationId: z.ZodString;
55
55
  actor: z.ZodObject<{
56
56
  kind: import("zod/mini").ZodMiniLiteral<"member">;
@@ -59,12 +59,12 @@ export declare const backgroundWakeSchema: z.ZodObject<{
59
59
  lane: z.ZodString;
60
60
  originMethod: z.ZodString;
61
61
  observed: z.ZodObject<{
62
- authorityVersion: z.ZodNumber;
62
+ authorityVersion: z.ZodLazy<z.ZodNumber>;
63
63
  artifactDigest: z.ZodCustom<Sha256Digest, Sha256Digest>;
64
- membershipVersion: z.ZodOptional<z.ZodNumber>;
64
+ membershipVersion: z.ZodOptional<z.ZodLazy<z.ZodNumber>>;
65
65
  }, z.core.$strict>;
66
- epoch: z.ZodNumber;
67
- }, z.core.$strict>;
66
+ epoch: z.ZodLazy<z.ZodNumber>;
67
+ }, z.core.$strict>>;
68
68
  /** A host wake cannot confer authority without fresh directory and method admission. */
69
69
  export type BackgroundWake = z.output<typeof backgroundWakeSchema>;
70
70
  /** A retained identity eligible for member-only replay. */
@@ -8,13 +8,13 @@ export { backgroundSyncAllowed } from "./internal/background-sync.js";
8
8
  /** The caller's single lightweight grammar for a host-sealed enqueue origin. */
9
9
  export const backgroundOriginSchema = appMethodCallerSchema.shape.backgroundOrigin.def.innerType;
10
10
  /** The closed result of checking a claimed job's origin in a fresh replay frame. */
11
- export const claimedJobAdmissionSchema = z.union([
11
+ export const claimedJobAdmissionSchema = z.lazy(() => z.union([
12
12
  z.strictObject({ kind: z.literal("admitted") }),
13
13
  z.strictObject({
14
14
  kind: z.literal("refused"),
15
15
  code: z.literal("access_changed"),
16
16
  }),
17
- ]);
17
+ ]));
18
18
  const originBytes = (claims) => new TextEncoder().encode(JSON.stringify([
19
19
  "fungi.background-origin/1",
20
20
  claims.instanceId,
@@ -110,9 +110,9 @@ export function mayEnqueueBackground(context) {
110
110
  Schema.is(WatchdogQueuedJobSchema.fields.lane)(context.backgroundLane));
111
111
  }
112
112
  const member = z.strictObject(hostActorSchema.def.options[0].shape);
113
- const revision = z.number().int().positive().max(Number.MAX_SAFE_INTEGER);
113
+ const revision = z.lazy(() => z.number().int().positive().max(Number.MAX_SAFE_INTEGER));
114
114
  /** Identity and observed revisions only. Unknown fields, including bearer material, refuse. */
115
- export const backgroundWakeSchema = z
115
+ export const backgroundWakeSchema = z.lazy(() => z
116
116
  .strictObject({
117
117
  installationId: z.string().min(1).max(256),
118
118
  actor: member,
@@ -130,7 +130,7 @@ export const backgroundWakeSchema = z
130
130
  })
131
131
  .refine((wake) => wake.lane === actorLane(wake.actor), {
132
132
  message: "Wake lane must name its member",
133
- });
133
+ }));
134
134
  /** The App can settle a refused lane without receiving any binding authority. */
135
135
  export const backgroundRefusalCodeSchema = z.enum([
136
136
  "access_changed",
@@ -10,4 +10,4 @@ export declare const gitRefUpdateSchema: z.ZodObject<{
10
10
  after: z.ZodString;
11
11
  }, z.core.$strict>;
12
12
  /** Host push event IDs include the Computer and local event identity. */
13
- export declare const gitPushEventIdSchema: z.ZodString;
13
+ export declare const gitPushEventIdSchema: z.ZodLazy<z.ZodString>;
@@ -13,4 +13,4 @@ export const gitRefUpdateSchema = z.strictObject({
13
13
  after: gitSha1Schema,
14
14
  });
15
15
  /** Host push event IDs include the Computer and local event identity. */
16
- export const gitPushEventIdSchema = z.string().min(1).max(512);
16
+ export const gitPushEventIdSchema = z.lazy(() => z.string().min(1).max(512));
@@ -1468,6 +1468,9 @@ export declare const decodeReleaseLifecycleStoreResult: (input: unknown, options
1468
1468
  pending?: true | undefined;
1469
1469
  hidden?: true | undefined;
1470
1470
  anonymous?: true | undefined;
1471
+ present?: Readonly<{
1472
+ verb: string;
1473
+ }> | undefined;
1471
1474
  }>>>;
1472
1475
  toolFamily?: Readonly<{
1473
1476
  name: string;
@@ -226,6 +226,9 @@ export declare const decodePublicWebsiteAuthorityStoreResult: (input: unknown, o
226
226
  pending?: true | undefined;
227
227
  hidden?: true | undefined;
228
228
  anonymous?: true | undefined;
229
+ present?: Readonly<{
230
+ verb: string;
231
+ }> | undefined;
229
232
  }>>>;
230
233
  toolFamily?: Readonly<{
231
234
  name: string;
package/docs/api/index.md CHANGED
@@ -2563,6 +2563,7 @@ const appCapabilityIds: readonly [
2563
2563
  "agent.list",
2564
2564
  "agent.manage",
2565
2565
  "agent.rename",
2566
+ "agent.avatar",
2566
2567
  "agent.toolPolicy",
2567
2568
  "agent.read",
2568
2569
  "agent.send",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fungi.computer/puffball",
3
- "version": "0.0.1",
3
+ "version": "0.1.0",
4
4
  "author": "Levi <levi@technomancy.dev>",
5
5
  "description": "Immutable App/Release catalog with verified public website delivery",
6
6
  "type": "module",
@@ -112,7 +112,7 @@
112
112
  "@fungi.computer/cloudflare-worker-bundler": "0.2.3-fungi.0",
113
113
  "zod": "4.4.3",
114
114
  "@fungi.computer/watchdog": "0.0.1",
115
- "@fungi.computer/gills": "0.0.1"
115
+ "@fungi.computer/gills": "0.1.0"
116
116
  },
117
117
  "devDependencies": {
118
118
  "@cloudflare/vitest-plugin": "1.1.2",