@fungi.computer/oyster 0.0.1 → 0.2.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 (195) hide show
  1. package/README.md +228 -176
  2. package/dist/agent-avatars.d.ts +103 -0
  3. package/dist/agent-avatars.js +66 -0
  4. package/dist/agents.d.ts +12 -2
  5. package/dist/agents.js +39 -2
  6. package/dist/app-builds.d.ts +76 -17
  7. package/dist/app-builds.js +207 -63
  8. package/dist/app-sources.d.ts +7 -22
  9. package/dist/app-sources.js +49 -14
  10. package/dist/apps/gate.d.ts +7 -7
  11. package/dist/apps/gate.js +6 -6
  12. package/dist/apps/installation.d.ts +35 -35
  13. package/dist/apps/installation.js +20 -19
  14. package/dist/build/artifact-writer.d.ts +40 -0
  15. package/dist/build/artifact-writer.js +181 -0
  16. package/dist/build/build-jobs.js +7 -1
  17. package/dist/build/build-policy.d.ts +10 -0
  18. package/dist/build/build-policy.js +10 -0
  19. package/dist/build/build-step.d.ts +12 -1
  20. package/dist/build/build-step.js +9 -1
  21. package/dist/build/candidate-builder.d.ts +68 -0
  22. package/dist/build/candidate-builder.js +91 -0
  23. package/dist/build/candidate-cli.d.ts +1 -0
  24. package/dist/build/candidate-cli.js +119 -0
  25. package/dist/build/candidate-cli.mjs +28220 -0
  26. package/dist/build/content-objects.d.ts +37 -0
  27. package/dist/build/content-objects.js +53 -0
  28. package/dist/build/effect.d.ts +18 -0
  29. package/dist/build/effect.js +52 -12
  30. package/dist/build/git-environment.d.ts +3 -0
  31. package/dist/build/git-environment.js +21 -9
  32. package/dist/build/local-build.d.ts +13 -3
  33. package/dist/build/local-build.js +149 -99
  34. package/dist/build/snapshot-package-store.d.ts +10 -0
  35. package/dist/build/snapshot-package-store.js +15 -0
  36. package/dist/build/snapshot-program-scripts.js +1 -1
  37. package/dist/build/snapshot-programs/snapshot-path.d.ts +2 -0
  38. package/dist/build/snapshot-programs/snapshot-path.js +6 -0
  39. package/dist/build/submission-contract.d.ts +461 -17
  40. package/dist/build/submission-contract.js +136 -26
  41. package/dist/build/workspace-build.d.ts +7 -2
  42. package/dist/build/workspace-build.js +55 -11
  43. package/dist/build-contract.d.ts +3 -0
  44. package/dist/build-contract.js +3 -0
  45. package/dist/build-egress.d.ts +62 -0
  46. package/dist/build-egress.js +148 -0
  47. package/dist/build.d.ts +1 -0
  48. package/dist/build.js +1 -0
  49. package/dist/cloudflare.js +4 -4
  50. package/dist/frame-binding-wire-script.js +1 -1
  51. package/dist/frame-binding-wire.d.ts +1 -1
  52. package/dist/frame-binding-wire.js +1 -1
  53. package/dist/git-journal.js +4 -4
  54. package/dist/index.d.ts +1 -0
  55. package/dist/index.js +1 -0
  56. package/dist/installation-consent.d.ts +3 -1
  57. package/dist/installation-consent.js +2 -0
  58. package/dist/mcp-owner.js +20 -8
  59. package/dist/pack.d.ts +6 -3
  60. package/dist/pack.js +28 -11
  61. package/dist/page/gill-observation.d.ts +4 -0
  62. package/dist/page/gill-observation.js +31 -0
  63. package/dist/page/mount.d.ts +4 -8
  64. package/dist/page/window-launch.d.ts +18 -0
  65. package/dist/page/window-launch.js +11 -0
  66. package/dist/page-script.js +4 -4
  67. package/dist/release.d.ts +11 -0
  68. package/dist/release.js +4 -1
  69. package/dist/shell/app-directory.d.ts +50 -45
  70. package/dist/shell/app-directory.js +19 -18
  71. package/dist/shell/shell-module.d.ts +26 -2
  72. package/dist/shell/shell-module.js +51 -2
  73. package/dist/shell/window-manager.d.ts +5 -1
  74. package/dist/shell/window-manager.js +21 -2
  75. package/dist/shell/workbench-directory.d.ts +332 -0
  76. package/dist/shell/workbench-directory.js +35 -0
  77. package/dist/shell/workbench-host-types.d.ts +1 -1
  78. package/dist/shell/workbench-host.js +5 -0
  79. package/dist/shell/workbench-model.d.ts +3 -1
  80. package/dist/source/index.d.ts +6 -7
  81. package/dist/source/index.js +6 -7
  82. package/dist/source/template-push.d.ts +33 -0
  83. package/dist/source/template-push.js +223 -0
  84. package/dist/source/template-repository.d.ts +2 -0
  85. package/dist/source/template-repository.js +13 -0
  86. package/dist/source/{template-write.d.ts → template-seed.d.ts} +19 -20
  87. package/dist/source/template-seed.js +80 -0
  88. package/dist/standalone/agent-directory.d.ts +4 -0
  89. package/dist/standalone/agent-directory.js +4 -0
  90. package/dist/standalone/agents.d.ts +227 -0
  91. package/dist/standalone/agents.js +834 -0
  92. package/dist/standalone/app-builds-binding.d.ts +36 -0
  93. package/dist/standalone/app-builds-binding.js +119 -0
  94. package/dist/standalone/app-set.d.ts +91 -0
  95. package/dist/standalone/app-set.js +395 -0
  96. package/dist/standalone/app-source.d.ts +41 -0
  97. package/dist/standalone/app-source.js +59 -0
  98. package/dist/standalone/builds.d.ts +18 -0
  99. package/dist/standalone/builds.js +101 -0
  100. package/dist/standalone/computer-egress.d.ts +37 -0
  101. package/dist/standalone/computer-egress.js +111 -0
  102. package/dist/standalone/computer.d.ts +122 -0
  103. package/dist/standalone/computer.js +714 -0
  104. package/dist/standalone/install-apps-cli.d.ts +2 -0
  105. package/dist/standalone/install-apps-cli.js +126 -0
  106. package/dist/standalone/instance.d.ts +35 -0
  107. package/dist/standalone/instance.js +74 -0
  108. package/dist/standalone/media.d.ts +76 -0
  109. package/dist/standalone/media.js +227 -0
  110. package/dist/standalone/preview.d.ts +51 -0
  111. package/dist/standalone/preview.js +167 -0
  112. package/dist/standalone/registry.d.ts +102 -0
  113. package/dist/standalone/registry.js +193 -0
  114. package/dist/standalone/tenancy.d.ts +42 -0
  115. package/dist/standalone/tenancy.js +241 -0
  116. package/dist/standalone/worker.d.ts +55 -0
  117. package/dist/standalone/worker.js +147 -0
  118. package/dist/standalone/workflow-authority-readers.d.ts +16 -0
  119. package/dist/standalone/workflow-authority-readers.js +35 -0
  120. package/dist/standalone/workflow-binding.d.ts +216 -0
  121. package/dist/standalone/workflow-binding.js +217 -0
  122. package/dist/standalone/workflow-events.d.ts +46 -0
  123. package/dist/standalone/workflow-events.js +39 -0
  124. package/dist/standalone/workflow-git-capture.d.ts +7 -0
  125. package/dist/standalone/workflow-git-capture.js +62 -0
  126. package/dist/standalone/workflow-host.d.ts +955 -0
  127. package/dist/standalone/workflow-host.js +778 -0
  128. package/dist/standalone/workflow-node-capture.d.ts +13 -0
  129. package/dist/standalone/workflow-node-capture.js +72 -0
  130. package/dist/standalone/workflow-root-authority.d.ts +27 -0
  131. package/dist/standalone/workflow-root-authority.js +87 -0
  132. package/dist/standalone/workflow-schedules.d.ts +52 -0
  133. package/dist/standalone/workflow-schedules.js +40 -0
  134. package/dist/standalone/workflow-trigger-host.d.ts +1716 -0
  135. package/dist/standalone/workflow-trigger-host.js +52 -0
  136. package/dist/standalone/workflows.d.ts +713 -0
  137. package/dist/standalone/workflows.js +554 -0
  138. package/dist/tenancy/auth0.d.ts +64 -0
  139. package/dist/tenancy/auth0.js +198 -0
  140. package/dist/tenancy/cloudflare/rate-limit.d.ts +8 -0
  141. package/dist/tenancy/cloudflare/rate-limit.js +19 -0
  142. package/dist/tenancy/cloudflare/registry.d.ts +50 -0
  143. package/dist/tenancy/cloudflare/registry.js +301 -0
  144. package/dist/tenancy/cloudflare.d.ts +2 -0
  145. package/dist/tenancy/cloudflare.js +2 -0
  146. package/dist/tenancy/cold-directory.d.ts +13 -0
  147. package/dist/tenancy/cold-directory.js +43 -0
  148. package/dist/tenancy/contracts.d.ts +195 -0
  149. package/dist/tenancy/contracts.js +1 -0
  150. package/dist/tenancy/index.d.ts +19 -0
  151. package/dist/tenancy/index.js +156 -0
  152. package/dist/tenancy/owner-key.d.ts +26 -0
  153. package/dist/tenancy/owner-key.js +63 -0
  154. package/dist/tenancy/oyster.d.ts +4 -0
  155. package/dist/tenancy/oyster.js +25 -0
  156. package/dist/tenancy/registry-record.d.ts +7 -0
  157. package/dist/tenancy/registry-record.js +44 -0
  158. package/dist/tenancy/registry.d.ts +27 -0
  159. package/dist/tenancy/registry.js +138 -0
  160. package/dist/tenancy/resolve.d.ts +7 -0
  161. package/dist/tenancy/resolve.js +64 -0
  162. package/dist/workers-git.js +1 -4
  163. package/dist/workers.d.ts +2 -2
  164. package/dist/workers.js +3 -1
  165. package/docs/api/build-contract.md +829 -32
  166. package/docs/api/build.md +253 -17
  167. package/docs/api/modules.md +40 -32
  168. package/docs/api/pack.md +6 -3
  169. package/docs/api/shell/app-directory.md +267 -0
  170. package/docs/api/shell/shell-module.md +64 -3
  171. package/docs/api/shell/workbench-directory.md +119 -0
  172. package/docs/api/shell/workbench.md +19 -0
  173. package/docs/api/shell.md +127 -0
  174. package/docs/api/tenancy/auth0.md +110 -0
  175. package/docs/api/tenancy/cloudflare.md +221 -0
  176. package/docs/api/tenancy/cold-directory.md +46 -0
  177. package/docs/api/tenancy/owner-key.md +63 -0
  178. package/docs/api/tenancy/registry.md +77 -0
  179. package/docs/api/tenancy/resolve.md +69 -0
  180. package/docs/api/tenancy.md +430 -0
  181. package/docs/api/workers-git.md +140 -21
  182. package/docs/api/workers.md +15 -2
  183. package/docs/site/agent-quickstart.mdx +52 -55
  184. package/examples/standalone/worker.ts +7 -14
  185. package/examples/standalone/wrangler.jsonc +67 -6
  186. package/package.json +78 -25
  187. package/dist/build/r2-artifact-writer.d.ts +0 -31
  188. package/dist/build/r2-artifact-writer.js +0 -179
  189. package/dist/source/template-write.js +0 -344
  190. package/docs/media/architecture.mmd +0 -32
  191. package/docs/media/architecture.png +0 -0
  192. package/docs/media/bonsai-network.png +0 -0
  193. package/docs/media/bonsai-repository.png +0 -0
  194. package/examples/git/worker.ts +0 -39
  195. package/examples/git/wrangler.jsonc +0 -32
package/dist/agents.d.ts CHANGED
@@ -10,11 +10,14 @@ import type { AppToolPolicy } from "./apps/tools.js";
10
10
  import * as Schema from "effect/Schema";
11
11
  import { type OysterCapability, type OysterEnv, type OysterPrincipal } from "./host.js";
12
12
  import type { HostActor } from "@fungi.computer/puffball/app";
13
+ import type { Avatar } from "@fungi.computer/sprite/avatar";
13
14
  import type { MemberInboxItem, MemberInboxSession } from "@fungi.computer/puffball/inbox";
14
15
  /** One agent as Apps see it, in Agar's `appAgentSchema` shape. */
15
16
  export type OysterAgent = Readonly<{
16
17
  agentId: string;
17
18
  name: string;
19
+ /** The Agent's own avatar: the owner's choice, else its seeded default. */
20
+ avatar: Avatar;
18
21
  sessionOperations: readonly ("agent.read" | "agent.send" | "agent.manage")[];
19
22
  }>;
20
23
  /** An Agent owner's Session facts before the member identity and visit are added. */
@@ -70,12 +73,19 @@ export type AgentToolPolicyStatus = Readonly<{
70
73
  export type OysterAgents = Readonly<{
71
74
  /** Every agent, oldest first. */
72
75
  list(): Promise<readonly OysterAgent[]>;
73
- /** Create an agent; retrying with the same `requestId` returns the same one. */
74
- create(name: string, requestId: string, principal: OysterPrincipal, actor: AgentPolicyActor): Promise<OysterAgent>;
76
+ /**
77
+ * Create an agent; retrying with the same `requestId` returns the same one.
78
+ * With no `avatar` it wears its seeded default until the owner picks one.
79
+ */
80
+ create(name: string, requestId: string, principal: OysterPrincipal, actor: AgentPolicyActor, avatar?: Avatar): Promise<OysterAgent>;
75
81
  /** Owner-only rename; refuses a name already held by another Agent. */
76
82
  rename(agentId: string, name: string, principal: OysterPrincipal): Promise<OysterAgent | Readonly<{
77
83
  error: "not_found" | "name_taken" | "not_granted";
78
84
  }>>;
85
+ /** Owner-only avatar change for an existing Agent. */
86
+ setAvatar(agentId: string, avatar: Avatar, principal: OysterPrincipal): Promise<OysterAgent | Readonly<{
87
+ error: "not_found" | "not_granted";
88
+ }>>;
79
89
  /** This Agent's App-tool policy status, or `null` for no such Agent. */
80
90
  policyStatus(agentId: string): Promise<AgentToolPolicyStatus | null>;
81
91
  /** Read this Agent's stored App-tool approval; absence requires re-approval. A key's App access is its own grants (Ear Tag), not this policy. */
package/dist/agents.js CHANGED
@@ -7,8 +7,10 @@
7
7
  */
8
8
  import { Hono } from "hono";
9
9
  import * as Schema from "effect/Schema";
10
+ import { z } from "zod";
10
11
  import { oysterPrincipalIsOwner, } from "./host.js";
11
- import { agentList, agentManage, agentRename, agentSessionRead, agentSessionWrite, agentToolPolicy, } from "@fungi.computer/agar/agents";
12
+ import { agentAvatarSchema } from "./agent-avatars.js";
13
+ import { agentAvatar, agentList, agentManage, agentRename, agentSessionRead, agentSessionWrite, agentToolPolicy, } from "@fungi.computer/agar/agents";
12
14
  /** At most this many MCP servers per Agent. */
13
15
  export const maxAgentMcpServers = 16;
14
16
  /** Owner input for one MCP server: a guest identifier, an `https:` endpoint and an optional bearer. */
@@ -30,10 +32,12 @@ export const agentMcpServerInputSchema = Schema.Struct({
30
32
  const createSchema = Schema.Struct({
31
33
  name: Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(256)),
32
34
  requestId: Schema.String.check(Schema.isPattern(/^[A-Za-z0-9_.:-]{1,256}$/u)),
35
+ avatar: Schema.optionalKey(Schema.Unknown),
33
36
  });
34
37
  const renameSchema = Schema.Struct({
35
38
  name: Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(256)),
36
39
  });
40
+ const avatarInputSchema = z.object({ avatar: agentAvatarSchema });
37
41
  const visitSchema = Schema.Struct({
38
42
  agentId: Schema.String,
39
43
  sessionId: Schema.String,
@@ -76,6 +80,19 @@ export function agentCapabilities(agents) {
76
80
  rename: { kind: "json", method: "PUT", path: "agent-names/:agentId" },
77
81
  },
78
82
  },
83
+ {
84
+ ...shared,
85
+ id: "agent.avatar",
86
+ permission: "agent.avatar",
87
+ version: agentAvatar.version,
88
+ methods: {
89
+ setAvatar: {
90
+ kind: "json",
91
+ method: "PUT",
92
+ path: "agent-avatars/:agentId",
93
+ },
94
+ },
95
+ },
79
96
  {
80
97
  ...shared,
81
98
  id: "agent.toolPolicy",
@@ -126,9 +143,14 @@ function createAgentRoutes(agents) {
126
143
  const body = Schema.decodeUnknownOption(createSchema)(await context.req.json());
127
144
  if (body._tag === "None")
128
145
  return refusal(400, "Name the agent");
146
+ const avatar = body.value.avatar === undefined
147
+ ? undefined
148
+ : agentAvatarSchema.safeParse(body.value.avatar);
149
+ if (avatar?.success === false)
150
+ return refusal(400, "Choose a valid avatar");
129
151
  // The owner's own authenticated request creates this Agent; its App tools
130
152
  // are approved the same way direct owner approval is, with no second path.
131
- return Response.json(await agents.create(body.value.name, body.value.requestId, principal, "owner-direct"));
153
+ return Response.json(await agents.create(body.value.name, body.value.requestId, principal, "owner-direct", avatar?.data));
132
154
  });
133
155
  routes.put("/agent-names/:agentId", async (context) => {
134
156
  const { principal } = context.env;
@@ -149,6 +171,21 @@ function createAgentRoutes(agents) {
149
171
  : 403, result.error);
150
172
  return Response.json(result);
151
173
  });
174
+ routes.put("/agent-avatars/:agentId", async (context) => {
175
+ const { principal } = context.env;
176
+ if (!oysterPrincipalIsOwner(principal))
177
+ return refusal(403, "Only the owner changes avatars");
178
+ const agentId = context.req.param("agentId");
179
+ if (!agentIdPattern.test(agentId))
180
+ return refusal(404, "No such agent");
181
+ const body = avatarInputSchema.safeParse(await context.req.json());
182
+ if (!body.success)
183
+ return refusal(400, "Choose a valid avatar");
184
+ const result = await agents.setAvatar(agentId, body.data.avatar, principal);
185
+ if ("error" in result)
186
+ return refusal(result.error === "not_found" ? 404 : 403, result.error);
187
+ return Response.json(result);
188
+ });
152
189
  routes.get("/agent-policies/:agentId", async (context) => {
153
190
  const agentId = context.req.param("agentId");
154
191
  if (!agentIdPattern.test(agentId))
@@ -1,20 +1,53 @@
1
+ /**
2
+ * Oyster's App build owner: an App's registered source, its build jobs on the
3
+ * host's own Computer, and the Releases those builds produce.
4
+ *
5
+ * A build runs the shared job lifecycle (`build/build-jobs.ts`) and the fixed
6
+ * captured builder command on one Computer. The Computer holds no key: its
7
+ * clone is admitted at egress for exactly the job's one repository (read
8
+ * only), and its candidate upload for exactly the job. A source is either a
9
+ * repository in an installation's Git (a fork, through the Git door) or the
10
+ * App's own published template, built only at a recorded seed revision of
11
+ * its pinned recipe (no installed App is needed). The build streams each
12
+ * built object into the host's artifact store itself, through the egress, and
13
+ * then submits a small manifest naming them. This owner only records facts:
14
+ * it checks each named object's stored size and digest, writes the asset
15
+ * manifest and App root in Oyster's one immutable artifact representation
16
+ * (the same objects a packed upload writes), verifies the Release like any
17
+ * installed one, and records it; installing it is a separate owner act.
18
+ */
1
19
  import * as Schema from "effect/Schema";
2
20
  import type { WatchdogSqliteOwner } from "@fungi.computer/watchdog";
3
21
  import { type Release } from "@fungi.computer/puffball";
4
- import { type TeamAppCandidateSubmission } from "./build/submission-contract.js";
5
- import { type PublisherR2Bucket } from "./build/r2-artifact-writer.js";
6
- import { type ArtifactStore } from "./release.js";
7
- /** A Computer's whole-build budget: a cold standard-2 build measured 185-270 s. */
22
+ import { type TeamAppCandidateManifest } from "./build/submission-contract.js";
23
+ import { type ArtifactHeads, type ArtifactStore } from "./release.js";
24
+ import type { PublisherTemplateSeedReceipts } from "./source/seed-receipt.js";
25
+ /** A Computer's whole-build budget: a cold build on a 6 GiB Computer measured 185-270 s. */
8
26
  export declare const oysterAppBuildTimeoutMs = 900000;
9
27
  /** Host names the Computer's egress serves for a build; never public hosts. */
10
28
  export declare const oysterBuildGitHost = "git.team.internal";
11
29
  export declare const oysterBuildReportHost = "build.team.internal";
12
- /** An App's registered build source: one repository and its pinned recipe. */
13
- export declare const oysterBuildSourceSchema: Schema.Struct<{
14
- readonly appId: Schema.refine<import("@fungi.computer/puffball").AppId, Schema.String>;
30
+ /** Where an App's source is cloned from. */
31
+ export declare const oysterBuildLocationSchema: Schema.Union<readonly [Schema.Struct<{
32
+ readonly kind: Schema.Literal<"installation">;
15
33
  /** The installation whose Git holds the repository (Bonsai for a fork). */
16
34
  readonly installationId: Schema.String;
17
35
  readonly repository: Schema.String;
36
+ }>, Schema.Struct<{
37
+ readonly kind: Schema.Literal<"template">;
38
+ }>]>;
39
+ export type OysterBuildLocation = Schema.Schema.Type<typeof oysterBuildLocationSchema>;
40
+ /** An App's registered build source: where it is cloned and its pinned recipe. */
41
+ export declare const oysterBuildSourceSchema: Schema.Struct<{
42
+ readonly appId: Schema.refine<import("@fungi.computer/puffball").AppId, Schema.String>;
43
+ readonly location: Schema.Union<readonly [Schema.Struct<{
44
+ readonly kind: Schema.Literal<"installation">;
45
+ /** The installation whose Git holds the repository (Bonsai for a fork). */
46
+ readonly installationId: Schema.String;
47
+ readonly repository: Schema.String;
48
+ }>, Schema.Struct<{
49
+ readonly kind: Schema.Literal<"template">;
50
+ }>]>;
18
51
  readonly recipe: Schema.Struct<{
19
52
  readonly kind: Schema.optional<Schema.Literals<readonly ["bundled-html", "source-html"]>>;
20
53
  readonly bundle: Schema.Literal<true>;
@@ -54,9 +87,10 @@ export type OysterBuildView = Readonly<{
54
87
  detail: string | null;
55
88
  release: Release | null;
56
89
  }>;
57
- /** One Computer as the build owner reaches it. */
58
90
  export type OysterBuildComputer = Readonly<{
59
- /** Run the fixed build command; the Computer re-admits the job first. */
91
+ /** Run the fixed build command; the Computer re-admits the job first.
92
+ * A missing `output` means no terminal result was established: the
93
+ * command may still be running, so it is never read as an exit. */
60
94
  runBuild(input: {
61
95
  jobId: string;
62
96
  command: string;
@@ -78,19 +112,27 @@ export type OysterAppBuildOptions = Readonly<{
78
112
  objectId: string;
79
113
  port: OysterBuildComputer;
80
114
  }>;
81
- bucket: PublisherR2Bucket;
82
- artifacts: ArtifactStore;
115
+ /** The host's artifact store; a build's objects are already in it. */
116
+ artifacts: ArtifactStore & ArtifactHeads;
117
+ /** The seed receipts a template build must match. */
118
+ templates: Pick<PublisherTemplateSeedReceipts, "read">;
83
119
  now?: () => number;
84
120
  }>;
85
- /** The SQLite tables one Oyster build owner keeps. */
86
- export declare function migrateOysterAppBuilds(owner: WatchdogSqliteOwner["sql"]): void;
87
- /** The build owner over one tenant's SQLite, Computer and Release bucket. */
121
+ /**
122
+ * The SQLite tables one Oyster build owner keeps. Creation and any carrying
123
+ * forward of retained facts run as one transaction of the owner's storage, so
124
+ * an interrupted conversion leaves the facts as they were for a retry.
125
+ */
126
+ export declare function migrateOysterAppBuilds(owner: WatchdogSqliteOwner): void;
127
+ /** The build owner over one tenant's SQLite, Computer and artifact store. */
88
128
  export declare function createOysterAppBuilds(options: OysterAppBuildOptions): Readonly<{
89
129
  /** Record (or replace) an App's build source; the caller is the owner. */
90
130
  registerSource(source: OysterBuildSource): OysterBuildSource;
91
131
  readSource: (appId: string) => OysterBuildSource | null;
92
132
  /**
93
133
  * Mint one build job for an App's registered source at one exact commit.
134
+ * A template source builds only a seed revision recorded for its pinned
135
+ * recipe.
94
136
  * Answers the job and its one run, which the caller keeps alive (the
95
137
  * upload grant exists only inside that run's fixed command).
96
138
  */
@@ -128,6 +170,11 @@ export declare function createOysterAppBuilds(options: OysterAppBuildOptions): R
128
170
  }>): Readonly<{
129
171
  requestedBy: string;
130
172
  }> | null;
173
+ /**
174
+ * May this Computer's clone read this template repository now? Only while
175
+ * a live template job on this Computer names it.
176
+ */
177
+ admitTemplateClone(computerObjectId: string, repository: string): boolean;
131
178
  /** A reported artifact or status for a live job. */
132
179
  record(event: Readonly<{
133
180
  kind: "build-artifact";
@@ -143,9 +190,21 @@ export declare function createOysterAppBuilds(options: OysterAppBuildOptions): R
143
190
  detail: string | null;
144
191
  }>): void;
145
192
  /**
146
- * The Computer's candidate for a live job: checked against the job, written
147
- * by the shared R2 writer, verified as an installable Release and recorded.
193
+ * May this live job's build upload one object now, and how large? The
194
+ * grant is the one inside the job's fixed command; the bound is its
195
+ * recipe's (`pinnedRecipeObjectBound`).
196
+ */
197
+ admitObjectUpload(jobId: string, computerObjectId: string, grant: string): Promise<Readonly<{
198
+ maxObjectBytes: number;
199
+ }> | null>;
200
+ /**
201
+ * The Computer's candidate manifest for a live job: checked against the
202
+ * job and its pinned recipe, each named object found stored with its
203
+ * size and verified digest (one at a time; only the backend descriptor
204
+ * is read), its asset manifest and App root written, verified as an
205
+ * installable Release and recorded. An over-policy candidate stores
206
+ * nothing.
148
207
  */
149
- submitCandidate(jobId: string, candidate: TeamAppCandidateSubmission, grant: string, credentialId: string): Promise<Response>;
208
+ submitCandidate(jobId: string, manifest: TeamAppCandidateManifest, grant: string, credentialId: string): Promise<Response>;
150
209
  }>;
151
210
  export type OysterAppBuilds = ReturnType<typeof createOysterAppBuilds>;