@fungi.computer/agar 0.0.0-stage → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +766 -2
  3. package/dist/agent-message-meta.d.ts +74 -0
  4. package/dist/agent-message-meta.js +63 -0
  5. package/dist/agents.d.ts +170 -0
  6. package/dist/agents.js +218 -0
  7. package/dist/app-build-contract.d.ts +43 -0
  8. package/dist/app-build-contract.js +24 -0
  9. package/dist/apps.d.ts +66 -0
  10. package/dist/apps.js +47 -0
  11. package/dist/backend-declaration.d.ts +6 -0
  12. package/dist/backend-declaration.js +65 -0
  13. package/dist/backend-definition.d.ts +88 -0
  14. package/dist/backend-definition.js +158 -0
  15. package/dist/backend-refusal.d.ts +10 -0
  16. package/dist/backend-refusal.js +10 -0
  17. package/dist/backend.d.ts +30 -0
  18. package/dist/backend.js +28 -0
  19. package/dist/capabilities.d.ts +30 -0
  20. package/dist/capabilities.js +50 -0
  21. package/dist/channels.d.ts +142 -0
  22. package/dist/channels.js +97 -0
  23. package/dist/commands.d.ts +33 -0
  24. package/dist/commands.js +46 -0
  25. package/dist/computer-contracts.d.ts +73 -0
  26. package/dist/computer-contracts.js +57 -0
  27. package/dist/computer.d.ts +294 -0
  28. package/dist/computer.js +319 -0
  29. package/dist/connect.d.ts +11 -0
  30. package/dist/connect.js +211 -0
  31. package/dist/errors.d.ts +34 -0
  32. package/dist/errors.js +106 -0
  33. package/dist/failure.d.ts +2 -0
  34. package/dist/failure.js +9 -0
  35. package/dist/files.d.ts +25 -0
  36. package/dist/files.js +84 -0
  37. package/dist/game-servers.d.ts +530 -0
  38. package/dist/game-servers.js +244 -0
  39. package/dist/gills.d.ts +43 -0
  40. package/dist/gills.js +174 -0
  41. package/dist/git-commit.d.ts +143 -0
  42. package/dist/git-commit.js +251 -0
  43. package/dist/git-rpc.d.ts +310 -0
  44. package/dist/git-rpc.js +166 -0
  45. package/dist/git-steps.d.ts +579 -0
  46. package/dist/git-steps.js +804 -0
  47. package/dist/git-wire.d.ts +33 -0
  48. package/dist/git-wire.js +240 -0
  49. package/dist/git.d.ts +322 -0
  50. package/dist/git.js +98 -0
  51. package/dist/host.d.ts +97 -0
  52. package/dist/host.js +732 -0
  53. package/dist/inbox.d.ts +99 -0
  54. package/dist/inbox.js +184 -0
  55. package/dist/index.d.ts +31 -0
  56. package/dist/index.js +15 -0
  57. package/dist/inference.d.ts +17 -0
  58. package/dist/inference.js +115 -0
  59. package/dist/internal/app-error.d.ts +8 -0
  60. package/dist/internal/app-error.js +36 -0
  61. package/dist/internal/app-session.d.ts +8 -0
  62. package/dist/internal/app-session.js +551 -0
  63. package/dist/internal/back-inputs.d.ts +22 -0
  64. package/dist/internal/back-inputs.js +93 -0
  65. package/dist/internal/browser-bridge.d.ts +30 -0
  66. package/dist/internal/browser-bridge.js +203 -0
  67. package/dist/internal/capabilities.d.ts +13 -0
  68. package/dist/internal/capabilities.js +138 -0
  69. package/dist/internal/commands.d.ts +9 -0
  70. package/dist/internal/commands.js +257 -0
  71. package/dist/internal/disconnect-host.d.ts +7 -0
  72. package/dist/internal/disconnect-host.js +19 -0
  73. package/dist/internal/git-edit-tree.d.ts +6 -0
  74. package/dist/internal/git-edit-tree.js +46 -0
  75. package/dist/internal/memory-fs.d.ts +39 -0
  76. package/dist/internal/memory-fs.js +154 -0
  77. package/dist/internal/protocol.d.ts +116 -0
  78. package/dist/internal/protocol.js +6 -0
  79. package/dist/internal/query-feed.d.ts +23 -0
  80. package/dist/internal/query-feed.js +111 -0
  81. package/dist/internal/result.d.ts +22 -0
  82. package/dist/internal/result.js +61 -0
  83. package/dist/internal/rpc-contract.d.ts +24 -0
  84. package/dist/internal/rpc-contract.js +78 -0
  85. package/dist/internal/schemas.d.ts +307 -0
  86. package/dist/internal/schemas.js +524 -0
  87. package/dist/internal/store.d.ts +8 -0
  88. package/dist/internal/store.js +30 -0
  89. package/dist/internal/terminal-gate.d.ts +17 -0
  90. package/dist/internal/terminal-gate.js +94 -0
  91. package/dist/lifecycle.d.ts +44 -0
  92. package/dist/lifecycle.js +1 -0
  93. package/dist/marketplace.d.ts +159 -0
  94. package/dist/marketplace.js +102 -0
  95. package/dist/media-json.d.ts +181 -0
  96. package/dist/media-json.js +204 -0
  97. package/dist/media-library.d.ts +11 -0
  98. package/dist/media-library.js +15 -0
  99. package/dist/media-request-id.d.ts +7 -0
  100. package/dist/media-request-id.js +16 -0
  101. package/dist/media.d.ts +354 -0
  102. package/dist/media.js +654 -0
  103. package/dist/method-refusal.d.ts +64 -0
  104. package/dist/method-refusal.js +48 -0
  105. package/dist/pending.d.ts +10 -0
  106. package/dist/pending.js +10 -0
  107. package/dist/query.d.ts +76 -0
  108. package/dist/query.js +195 -0
  109. package/dist/react-mount.d.ts +23 -0
  110. package/dist/react-mount.js +108 -0
  111. package/dist/react.d.ts +41 -0
  112. package/dist/react.js +111 -0
  113. package/dist/read-copy.d.ts +103 -0
  114. package/dist/read-copy.js +195 -0
  115. package/dist/roles/files.d.ts +295 -0
  116. package/dist/roles/files.js +184 -0
  117. package/dist/root.d.ts +21 -0
  118. package/dist/root.js +1 -0
  119. package/dist/rpc.d.ts +1 -0
  120. package/dist/rpc.js +1 -0
  121. package/dist/status.d.ts +17 -0
  122. package/dist/status.js +50 -0
  123. package/dist/storage-wire.d.ts +167 -0
  124. package/dist/storage-wire.js +115 -0
  125. package/dist/storage.d.ts +72 -0
  126. package/dist/storage.js +143 -0
  127. package/dist/store.d.ts +11 -0
  128. package/dist/store.js +1 -0
  129. package/dist/test-kit/git.d.ts +31 -0
  130. package/dist/test-kit/git.js +174 -0
  131. package/dist/ui.d.ts +169 -0
  132. package/dist/ui.js +10 -0
  133. package/dist/window.d.ts +41 -0
  134. package/dist/window.js +15 -0
  135. package/dist/world.d.ts +16 -0
  136. package/dist/world.js +17 -0
  137. package/docs/api/README.md +28 -0
  138. package/docs/api/app-build-contract.md +113 -0
  139. package/docs/api/backend-declaration.md +62 -0
  140. package/docs/api/backend-definition.md +215 -0
  141. package/docs/api/backend.md +269 -0
  142. package/docs/api/errors.md +169 -0
  143. package/docs/api/files.md +91 -0
  144. package/docs/api/gills.md +164 -0
  145. package/docs/api/git-commit.md +279 -0
  146. package/docs/api/git-rpc.md +243 -0
  147. package/docs/api/git-steps.md +1010 -0
  148. package/docs/api/git-wire.md +197 -0
  149. package/docs/api/git.md +579 -0
  150. package/docs/api/index.md +2880 -0
  151. package/docs/api/media-json.md +507 -0
  152. package/docs/api/media-request-id.md +32 -0
  153. package/docs/api/modules.md +32 -0
  154. package/docs/api/query.md +253 -0
  155. package/docs/api/react.md +216 -0
  156. package/docs/api/read-copy.md +204 -0
  157. package/docs/api/rpc.md +128 -0
  158. package/docs/api/storage.md +620 -0
  159. package/package.json +197 -3
@@ -0,0 +1,33 @@
1
+ /** Git smart-HTTP packet grammar shared by host doors and CAS writers. */
2
+ import type { GitPushVerdict, GitRefUpdate } from "./git.js";
3
+ /** Split pkt-lines from the start of `bytes`; stops at the first flush when asked. */
4
+ export declare function readPacketLines(bytes: Uint8Array, stopAtFlush: boolean, strict?: boolean): Uint8Array[];
5
+ /** Encode one UTF-8 text packet with its byte-counted four-byte Git header. */
6
+ export declare function pktLine(text: string): string;
7
+ /** Refs the provider accepted, read from report-status (with or without side-band). */
8
+ export declare function acceptedRefs(response: Uint8Array, sideBand: boolean): ReadonlySet<string>;
9
+ /** The decoded receive-pack command section; pack bytes remain unopened. */
10
+ export type ReceivePack = Readonly<{
11
+ kind: "ok";
12
+ updates: readonly GitRefUpdate[];
13
+ capabilities: readonly string[];
14
+ }> | Readonly<{
15
+ /** A lone flush: the probe Git sends before a chunked (large) push to
16
+ * check authentication; it updates nothing. */
17
+ kind: "probe";
18
+ }> | Readonly<{
19
+ kind: "invalid";
20
+ reason: "unparsable" | "push-cert" | "too-many";
21
+ }>;
22
+ /** Fail closed on any command the maintained Git wire contract does not support. */
23
+ export declare function parseReceivePack(body: Uint8Array): ReceivePack;
24
+ /** Whole-push refusal in report-status, including the negotiated side-band framing. */
25
+ export declare function refusalReport(verdict: GitPushVerdict & {
26
+ allowed: false;
27
+ }, updates: readonly GitRefUpdate[], capabilities: readonly string[]): Uint8Array;
28
+ /** Data channel of an upload-pack side-band reply; fatal server messages refuse. */
29
+ export declare function sideBandData(body: Uint8Array): Uint8Array;
30
+ /** Ref names and object IDs from the maintained smart-HTTP advertisement framing. */
31
+ export declare function advertisedRefs(body: Uint8Array): ReadonlyMap<string, string>;
32
+ /** Capabilities from the ref advertisement's first NUL-delimited capability list. */
33
+ export declare function advertisedCapabilities(body: Uint8Array): ReadonlySet<string>;
@@ -0,0 +1,240 @@
1
+ const decoder = new TextDecoder();
2
+ const encoder = new TextEncoder();
3
+ const ZERO = "0".repeat(40);
4
+ const pushDecoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
5
+ class InvalidPushRequest extends Error {
6
+ reason;
7
+ constructor(message, options, reason = "unparsable") {
8
+ super(message, options);
9
+ this.reason = reason;
10
+ }
11
+ }
12
+ /** Strict client headers must be hexadecimal; provider status retains tolerant decoding. */
13
+ function packetHeader(bytes, offset, strict) {
14
+ const header = decoder.decode(bytes.subarray(offset, offset + 4));
15
+ if (strict && !/^[0-9a-f]{4}$/iu.test(header))
16
+ throw new InvalidPushRequest("Invalid Git push packet");
17
+ return Number.parseInt(header, 16);
18
+ }
19
+ /** Decode one packet's framing without consuming payload or a following pack. */
20
+ function packetLength(bytes, offset, strict) {
21
+ const length = packetHeader(bytes, offset, strict);
22
+ if (Number.isNaN(length))
23
+ return null;
24
+ if (strict && length === 1)
25
+ throw new InvalidPushRequest("Unsupported Git push delimiter");
26
+ if (length <= 1)
27
+ return length;
28
+ if (length < 4 || offset + length > bytes.length) {
29
+ if (strict)
30
+ throw new InvalidPushRequest("Truncated Git push packet");
31
+ return null;
32
+ }
33
+ return length;
34
+ }
35
+ /** Command bounds apply before decoding; provider status packets remain tolerant. */
36
+ function packetContent(bytes, offset, length, count, strict) {
37
+ if (strict && count >= 256)
38
+ throw new InvalidPushRequest("Too many Git push commands", undefined, "too-many");
39
+ return bytes.subarray(offset + 4, offset + length);
40
+ }
41
+ /** Split pkt-lines from the start of `bytes`; stops at the first flush when asked. */
42
+ export function readPacketLines(bytes, stopAtFlush, strict = false) {
43
+ const lines = [];
44
+ let offset = 0;
45
+ let flushed = false;
46
+ while (offset + 4 <= bytes.length) {
47
+ const length = packetLength(bytes, offset, strict);
48
+ if (length === null)
49
+ break;
50
+ if (length <= 1) {
51
+ offset += 4;
52
+ if (stopAtFlush && length === 0) {
53
+ flushed = true;
54
+ break;
55
+ }
56
+ continue;
57
+ }
58
+ lines.push(packetContent(bytes, offset, length, lines.length, strict));
59
+ offset += length;
60
+ }
61
+ if (strict && !flushed)
62
+ throw new InvalidPushRequest("Git push command section has no flush");
63
+ return lines;
64
+ }
65
+ /** Encode one UTF-8 text packet with its byte-counted four-byte Git header. */
66
+ export function pktLine(text) {
67
+ return (encoder.encode(text).length + 4).toString(16).padStart(4, "0") + text;
68
+ }
69
+ const COMMAND = /^([0-9a-f]{40}) ([0-9a-f]{40}) (refs\/[^\s\0]+)$/iu;
70
+ /** A shallow client's graft boundary, sent before its commands
71
+ * (pack-protocol `update-request = *shallow command-list`). */
72
+ const SHALLOW = /^shallow [0-9a-f]{40}\n?$/iu;
73
+ /** Decode exactly the command and optional capability fields supplied by the client. */
74
+ function pushFields(raw) {
75
+ let text;
76
+ try {
77
+ text = pushDecoder.decode(raw);
78
+ }
79
+ catch (cause) {
80
+ throw new InvalidPushRequest("Invalid Git push command encoding", {
81
+ cause,
82
+ });
83
+ }
84
+ const fields = text.replace(/\n$/u, "").split("\0");
85
+ if (fields.length > 2)
86
+ throw new InvalidPushRequest("Invalid Git push command capabilities");
87
+ return fields;
88
+ }
89
+ function refCommand(line) {
90
+ const match = COMMAND.exec(line);
91
+ if (!match) {
92
+ const signed = line.startsWith("push-cert");
93
+ throw new InvalidPushRequest(signed ? "Unsupported push-cert command" : "Unsupported Git push command", undefined, signed ? "push-cert" : "unparsable");
94
+ }
95
+ const [, before = ZERO, after = ZERO, ref = ""] = match;
96
+ return { before: before.toLowerCase(), after: after.toLowerCase(), ref };
97
+ }
98
+ function pushCapabilities(caps, commandIndex) {
99
+ if (caps === undefined)
100
+ return undefined;
101
+ if (commandIndex !== 0)
102
+ throw new InvalidPushRequest("Git push capabilities must accompany the first command");
103
+ const capabilities = caps.split(" ").filter(Boolean);
104
+ if (capabilities.some((capability) => capability === "push-cert" || capability.startsWith("push-cert=")))
105
+ throw new InvalidPushRequest("Signed Git pushes (push-cert) are not supported", undefined, "push-cert");
106
+ return capabilities;
107
+ }
108
+ /** The ref commands a client sends before its pack, and its capabilities. */
109
+ function pushRequest(body) {
110
+ const commands = [];
111
+ let capabilities = [];
112
+ const lines = readPacketLines(body, true, true);
113
+ // A push from a shallow repository (for example a `--depth 1` clone)
114
+ // names its graft boundaries first; the server only needs the commands.
115
+ const first = lines.findIndex((line) => !SHALLOW.test(decoder.decode(line)));
116
+ for (const raw of first === -1 ? [] : lines.slice(first)) {
117
+ const [line = "", caps] = pushFields(raw);
118
+ const command = refCommand(line);
119
+ const nextCapabilities = pushCapabilities(caps, commands.length);
120
+ commands.push(command);
121
+ if (nextCapabilities !== undefined)
122
+ capabilities = nextCapabilities;
123
+ }
124
+ if (commands.length === 0)
125
+ throw new InvalidPushRequest("Empty Git push command section");
126
+ return { commands, capabilities };
127
+ }
128
+ /** Refs the provider accepted, read from report-status (with or without side-band). */
129
+ export function acceptedRefs(response, sideBand) {
130
+ let status = response;
131
+ if (sideBand) {
132
+ const parts = readPacketLines(response, false)
133
+ .filter((line) => line[0] === 1)
134
+ .map((line) => line.subarray(1));
135
+ status = new Uint8Array(parts.reduce((size, part) => size + part.length, 0));
136
+ let offset = 0;
137
+ for (const part of parts) {
138
+ status.set(part, offset);
139
+ offset += part.length;
140
+ }
141
+ }
142
+ const accepted = new Set();
143
+ for (const raw of readPacketLines(status, false)) {
144
+ const text = decoder.decode(raw).replace(/\n$/u, "");
145
+ if (text.startsWith("ok "))
146
+ accepted.add(text.slice(3));
147
+ }
148
+ return accepted;
149
+ }
150
+ /** Fail closed on any command the maintained Git wire contract does not support. */
151
+ export function parseReceivePack(body) {
152
+ if (body.byteLength === 4 && decoder.decode(body) === "0000")
153
+ return { kind: "probe" };
154
+ try {
155
+ const push = pushRequest(body);
156
+ return {
157
+ kind: "ok",
158
+ updates: push.commands,
159
+ capabilities: push.capabilities,
160
+ };
161
+ }
162
+ catch (cause) {
163
+ if (!(cause instanceof InvalidPushRequest))
164
+ throw cause;
165
+ return { kind: "invalid", reason: cause.reason };
166
+ }
167
+ }
168
+ /** Whole-push refusal in report-status, including the negotiated side-band framing. */
169
+ export function refusalReport(verdict, updates, capabilities) {
170
+ const messages = new Map(verdict.refused.map(({ ref, message }) => [ref, message]));
171
+ const report = pktLine("unpack ok\n") +
172
+ updates
173
+ .map(({ ref }) => pktLine(`ng ${ref} ${(messages.get(ref) ?? "another ref in this push was refused").replace(/[\r\n\0]/gu, " ")}\n`))
174
+ .join("") +
175
+ "0000";
176
+ if (!capabilities.includes("side-band") &&
177
+ !capabilities.includes("side-band-64k"))
178
+ return encoder.encode(report);
179
+ const bytes = encoder.encode(report);
180
+ const chunkSize = capabilities.includes("side-band-64k") ? 65515 : 995;
181
+ const chunks = Math.ceil(bytes.byteLength / chunkSize);
182
+ const output = new Uint8Array(bytes.byteLength + chunks * 5 + 4);
183
+ let offset = 0;
184
+ for (let start = 0; start < bytes.byteLength; start += chunkSize) {
185
+ const chunk = bytes.subarray(start, start + chunkSize);
186
+ output.set(encoder.encode((chunk.byteLength + 5).toString(16).padStart(4, "0")), offset);
187
+ output[offset + 4] = 1;
188
+ output.set(chunk, offset + 5);
189
+ offset += chunk.byteLength + 5;
190
+ }
191
+ output.set(encoder.encode("0000"), offset);
192
+ return output;
193
+ }
194
+ /** Data channel of an upload-pack side-band reply; fatal server messages refuse. */
195
+ export function sideBandData(body) {
196
+ const chunks = [];
197
+ for (const packet of readPacketLines(body, false)) {
198
+ if (packet[0] === 3)
199
+ throw new Error(decoder.decode(packet.subarray(1)));
200
+ if (packet[0] === 1)
201
+ chunks.push(packet.subarray(1));
202
+ else if (decoder.decode(packet).startsWith("ERR "))
203
+ throw new Error(decoder.decode(packet));
204
+ }
205
+ const result = new Uint8Array(chunks.reduce((size, chunk) => size + chunk.length, 0));
206
+ let offset = 0;
207
+ for (const chunk of chunks) {
208
+ result.set(chunk, offset);
209
+ offset += chunk.length;
210
+ }
211
+ return result;
212
+ }
213
+ /** Ref names and object IDs from the maintained smart-HTTP advertisement framing. */
214
+ export function advertisedRefs(body) {
215
+ const refs = new Map();
216
+ for (const raw of readPacketLines(body, false)) {
217
+ const line = decoder.decode(raw).replace(/\n$/u, "");
218
+ if (line.startsWith("#"))
219
+ continue;
220
+ const [entry = ""] = line.split("\0");
221
+ const [oid = "", name = ""] = entry.split(" ");
222
+ if (/^[0-9a-f]{40}$/u.test(oid) && name.startsWith("refs/"))
223
+ refs.set(name, oid);
224
+ }
225
+ return refs;
226
+ }
227
+ /** Capabilities from the ref advertisement's first NUL-delimited capability list. */
228
+ export function advertisedCapabilities(body) {
229
+ for (const raw of readPacketLines(body, false)) {
230
+ const line = decoder.decode(raw);
231
+ const separator = line.indexOf("\0");
232
+ if (separator >= 0)
233
+ return new Set(line
234
+ .slice(separator + 1)
235
+ .trim()
236
+ .split(" ")
237
+ .filter(Boolean));
238
+ }
239
+ return new Set();
240
+ }
package/dist/git.d.ts ADDED
@@ -0,0 +1,322 @@
1
+ import { gitRepositoryNameSchema } from "@fungi.computer/puffball/git-representation";
2
+ import * as z from "zod";
3
+ import { type HostActor, type WorkflowAttestation } from "@fungi.computer/puffball/app-method-runtime";
4
+ /** Requested installation-scoped Git authority; a declaration is never a grant. */
5
+ export declare const gitRepositoryCapability = "git.repository";
6
+ /** Local repository name decoded at a host's repository boundary. */
7
+ export type GitRepositoryName = z.output<typeof gitRepositoryNameSchema>;
8
+ /**
9
+ * Host-selected repository namespace. Team identity comes from the host;
10
+ * decoding this reference never grants access to either namespace.
11
+ */
12
+ export declare const repositoryRefSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
13
+ kind: z.ZodLiteral<"installation">;
14
+ installationId: z.ZodString;
15
+ repository: z.ZodString;
16
+ }, z.core.$strict>, z.ZodObject<{
17
+ kind: z.ZodLiteral<"team-source">;
18
+ repository: z.ZodString;
19
+ }, z.core.$strict>], "kind">;
20
+ /** Installation-local repository or registered Team source, selected by its host. */
21
+ export type RepositoryRef = z.output<typeof repositoryRefSchema>;
22
+ /** Stable namespace identity, serialized through the canonical repository decoder. */
23
+ export declare function repositoryRefKey(repository: RepositoryRef): string;
24
+ /** Compare repository namespace and coordinates independently of allocation or property order. */
25
+ export declare function repositoryRefsEqual(left: RepositoryRef, right: RepositoryRef): boolean;
26
+ /** Host-held writer identity; Workflow attribution reuses Puffball's sole grammar. */
27
+ export type GitWriter = Readonly<{
28
+ kind: "actor";
29
+ actor: HostActor;
30
+ role?: "owner" | "member";
31
+ workflow?: WorkflowAttestation & {
32
+ branches: readonly string[];
33
+ };
34
+ }> | Readonly<{
35
+ kind: "installation";
36
+ installationId: string;
37
+ onBehalfOf: HostActor | null;
38
+ }>;
39
+ /** Canonical Git writer decoder; identity is attested by a host, never by an App. */
40
+ export declare const gitWriterSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
41
+ kind: z.ZodLiteral<"actor">;
42
+ actor: z.ZodDiscriminatedUnion<[z.ZodObject<{
43
+ kind: import("zod/mini").ZodMiniLiteral<"member">;
44
+ memberId: import("zod/mini").ZodMiniString<string>;
45
+ }, z.core.$strict>, z.ZodObject<{
46
+ kind: import("zod/mini").ZodMiniLiteral<"agent">;
47
+ agentId: import("zod/mini").ZodMiniString<string>;
48
+ }, z.core.$strict>, z.ZodObject<{
49
+ kind: import("zod/mini").ZodMiniLiteral<"team-key">;
50
+ keyId: import("zod/mini").ZodMiniString<string>;
51
+ }, z.core.$strict>], "kind">;
52
+ role: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniEnum<{
53
+ member: "member";
54
+ owner: "owner";
55
+ }>>;
56
+ workflow: z.ZodOptional<z.ZodObject<{
57
+ armedBy: z.ZodDiscriminatedUnion<[z.ZodObject<{
58
+ kind: import("zod/mini").ZodMiniLiteral<"member">;
59
+ memberId: import("zod/mini").ZodMiniString<string>;
60
+ }, z.core.$strict>, z.ZodObject<{
61
+ kind: import("zod/mini").ZodMiniLiteral<"agent">;
62
+ agentId: import("zod/mini").ZodMiniString<string>;
63
+ }, z.core.$strict>, z.ZodObject<{
64
+ kind: import("zod/mini").ZodMiniLiteral<"team-key">;
65
+ keyId: import("zod/mini").ZodMiniString<string>;
66
+ }, z.core.$strict>], "kind">;
67
+ branches: z.ZodArray<z.ZodString>;
68
+ workflowId: import("zod/mini").ZodMiniString<string>;
69
+ runId: import("zod/mini").ZodMiniString<string>;
70
+ nodeId: import("zod/mini").ZodMiniString<string>;
71
+ }, z.core.$strict>>;
72
+ }, z.core.$strict>, z.ZodObject<{
73
+ kind: z.ZodLiteral<"installation">;
74
+ installationId: z.ZodString;
75
+ onBehalfOf: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
76
+ kind: import("zod/mini").ZodMiniLiteral<"member">;
77
+ memberId: import("zod/mini").ZodMiniString<string>;
78
+ }, z.core.$strict>, z.ZodObject<{
79
+ kind: import("zod/mini").ZodMiniLiteral<"agent">;
80
+ agentId: import("zod/mini").ZodMiniString<string>;
81
+ }, z.core.$strict>, z.ZodObject<{
82
+ kind: import("zod/mini").ZodMiniLiteral<"team-key">;
83
+ keyId: import("zod/mini").ZodMiniString<string>;
84
+ }, z.core.$strict>], "kind">>;
85
+ }, z.core.$strict>], "kind">;
86
+ /** The App's question covers the whole push, under host-held attribution. */
87
+ export declare const gitPushQuestionSchema: z.ZodObject<{
88
+ repository: z.ZodString;
89
+ writer: z.ZodObject<{
90
+ kind: z.ZodLiteral<"actor">;
91
+ actor: z.ZodDiscriminatedUnion<[z.ZodObject<{
92
+ kind: import("zod/mini").ZodMiniLiteral<"member">;
93
+ memberId: import("zod/mini").ZodMiniString<string>;
94
+ }, z.core.$strict>, z.ZodObject<{
95
+ kind: import("zod/mini").ZodMiniLiteral<"agent">;
96
+ agentId: import("zod/mini").ZodMiniString<string>;
97
+ }, z.core.$strict>, z.ZodObject<{
98
+ kind: import("zod/mini").ZodMiniLiteral<"team-key">;
99
+ keyId: import("zod/mini").ZodMiniString<string>;
100
+ }, z.core.$strict>], "kind">;
101
+ role: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniEnum<{
102
+ member: "member";
103
+ owner: "owner";
104
+ }>>;
105
+ workflow: z.ZodOptional<z.ZodObject<{
106
+ armedBy: z.ZodDiscriminatedUnion<[z.ZodObject<{
107
+ kind: import("zod/mini").ZodMiniLiteral<"member">;
108
+ memberId: import("zod/mini").ZodMiniString<string>;
109
+ }, z.core.$strict>, z.ZodObject<{
110
+ kind: import("zod/mini").ZodMiniLiteral<"agent">;
111
+ agentId: import("zod/mini").ZodMiniString<string>;
112
+ }, z.core.$strict>, z.ZodObject<{
113
+ kind: import("zod/mini").ZodMiniLiteral<"team-key">;
114
+ keyId: import("zod/mini").ZodMiniString<string>;
115
+ }, z.core.$strict>], "kind">;
116
+ branches: z.ZodArray<z.ZodString>;
117
+ workflowId: import("zod/mini").ZodMiniString<string>;
118
+ runId: import("zod/mini").ZodMiniString<string>;
119
+ nodeId: import("zod/mini").ZodMiniString<string>;
120
+ }, z.core.$strict>>;
121
+ }, z.core.$strict>;
122
+ updates: z.ZodArray<z.ZodObject<{
123
+ ref: z.ZodString;
124
+ before: z.ZodString;
125
+ after: z.ZodString;
126
+ }, z.core.$strict>>;
127
+ }, z.core.$strict>;
128
+ /** A whole push verdict; refusal messages are shown by ordinary Git clients. */
129
+ export declare const gitPushVerdictSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
130
+ allowed: z.ZodLiteral<true>;
131
+ }, z.core.$strict>, z.ZodObject<{
132
+ allowed: z.ZodLiteral<false>;
133
+ refused: z.ZodArray<z.ZodObject<{
134
+ ref: z.ZodString;
135
+ message: z.ZodString;
136
+ }, z.core.$strict>>;
137
+ }, z.core.$strict>], "allowed">;
138
+ /** Ref question sent only after host grant and Workflow branch admission. */
139
+ export type GitPushQuestion = z.output<typeof gitPushQuestionSchema>;
140
+ /** Explicit permission or bounded per-ref refusal for the whole push. */
141
+ export type GitPushVerdict = z.output<typeof gitPushVerdictSchema>;
142
+ /** One accepted push, with host attribution and no remote or credential. */
143
+ export declare const appGitPushFactSchema: z.ZodObject<{
144
+ repository: z.ZodString;
145
+ writer: z.ZodDiscriminatedUnion<[z.ZodObject<{
146
+ kind: z.ZodLiteral<"actor">;
147
+ actor: z.ZodDiscriminatedUnion<[z.ZodObject<{
148
+ kind: import("zod/mini").ZodMiniLiteral<"member">;
149
+ memberId: import("zod/mini").ZodMiniString<string>;
150
+ }, z.core.$strict>, z.ZodObject<{
151
+ kind: import("zod/mini").ZodMiniLiteral<"agent">;
152
+ agentId: import("zod/mini").ZodMiniString<string>;
153
+ }, z.core.$strict>, z.ZodObject<{
154
+ kind: import("zod/mini").ZodMiniLiteral<"team-key">;
155
+ keyId: import("zod/mini").ZodMiniString<string>;
156
+ }, z.core.$strict>], "kind">;
157
+ role: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniEnum<{
158
+ member: "member";
159
+ owner: "owner";
160
+ }>>;
161
+ workflow: z.ZodOptional<z.ZodObject<{
162
+ armedBy: z.ZodDiscriminatedUnion<[z.ZodObject<{
163
+ kind: import("zod/mini").ZodMiniLiteral<"member">;
164
+ memberId: import("zod/mini").ZodMiniString<string>;
165
+ }, z.core.$strict>, z.ZodObject<{
166
+ kind: import("zod/mini").ZodMiniLiteral<"agent">;
167
+ agentId: import("zod/mini").ZodMiniString<string>;
168
+ }, z.core.$strict>, z.ZodObject<{
169
+ kind: import("zod/mini").ZodMiniLiteral<"team-key">;
170
+ keyId: import("zod/mini").ZodMiniString<string>;
171
+ }, z.core.$strict>], "kind">;
172
+ branches: z.ZodArray<z.ZodString>;
173
+ workflowId: import("zod/mini").ZodMiniString<string>;
174
+ runId: import("zod/mini").ZodMiniString<string>;
175
+ nodeId: import("zod/mini").ZodMiniString<string>;
176
+ }, z.core.$strict>>;
177
+ }, z.core.$strict>, z.ZodObject<{
178
+ kind: z.ZodLiteral<"installation">;
179
+ installationId: z.ZodString;
180
+ onBehalfOf: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
181
+ kind: import("zod/mini").ZodMiniLiteral<"member">;
182
+ memberId: import("zod/mini").ZodMiniString<string>;
183
+ }, z.core.$strict>, z.ZodObject<{
184
+ kind: import("zod/mini").ZodMiniLiteral<"agent">;
185
+ agentId: import("zod/mini").ZodMiniString<string>;
186
+ }, z.core.$strict>, z.ZodObject<{
187
+ kind: import("zod/mini").ZodMiniLiteral<"team-key">;
188
+ keyId: import("zod/mini").ZodMiniString<string>;
189
+ }, z.core.$strict>], "kind">>;
190
+ }, z.core.$strict>], "kind">;
191
+ updates: z.ZodArray<z.ZodObject<{
192
+ ref: z.ZodString;
193
+ before: z.ZodString;
194
+ after: z.ZodString;
195
+ }, z.core.$strict>>;
196
+ unexplained: z.ZodOptional<z.ZodArray<z.ZodObject<{
197
+ ref: z.ZodString;
198
+ journaled: z.ZodNullable<z.ZodString>;
199
+ }, z.core.$strict>>>;
200
+ eventId: z.ZodString;
201
+ }, z.core.$strict>;
202
+ /** One bounded ref update, shared by push questions and accepted facts. */
203
+ export type GitRefUpdate = z.output<typeof appGitPushFactSchema>["updates"][number];
204
+ /** Host-delivered push fact; retries retain the same event ID. */
205
+ export type AppGitPushFact = z.output<typeof appGitPushFactSchema>;
206
+ /** App-owned lifecycle handler, separate from its callable method catalog. */
207
+ export type AppGitLifecycle = Readonly<{
208
+ /** An absent authorization handler refuses external pushes. */
209
+ authorizeGitPush?: (question: GitPushQuestion) => Promise<GitPushVerdict>;
210
+ /** Handle an accepted push; persist eventId with the effects to make retries idempotent. */
211
+ onGitPush?: (fact: AppGitPushFact) => Promise<void>;
212
+ }>;
213
+ /** Parse a host-admitted fact and invoke its lifecycle handler, preserving rejection. */
214
+ export declare function dispatchAppGitPush(lifecycle: AppGitLifecycle, raw: unknown): Promise<void>;
215
+ /** Credential-free repository metadata, with installation-local names. */
216
+ export type GitRepositoryInfo = Readonly<{
217
+ /** Local repository name. */
218
+ name: string;
219
+ /** Default branch, without the refs/heads prefix. */
220
+ defaultBranch: string;
221
+ /** ISO timestamp of the last push, or null before the first push. */
222
+ lastPushAt: string | null;
223
+ /** Local fork source, or null for a newly created repository. */
224
+ source: string | null;
225
+ }>;
226
+ /** Artifacts commit metadata, with the provider's credential fields absent. */
227
+ export type GitCommit = Readonly<{
228
+ /** SHA-1 commit ID. */
229
+ hash: string;
230
+ /** SHA-1 root tree ID. */
231
+ treeHash: string;
232
+ /** Commit message. */
233
+ message: string;
234
+ /** Author identity recorded in the commit. */
235
+ author: {
236
+ name: string;
237
+ email: string;
238
+ };
239
+ /** Committer identity recorded in the commit. */
240
+ committer: {
241
+ name: string;
242
+ email: string;
243
+ };
244
+ /** Parent commit IDs, in Git order. */
245
+ parents: string[];
246
+ /** Author timestamp, in Unix seconds. */
247
+ authoredAt: number;
248
+ /** Committer timestamp, in Unix seconds. */
249
+ committedAt: number;
250
+ }>;
251
+ /** One immediate child of a Git tree. */
252
+ export type GitTreeEntry = Readonly<{
253
+ /** Name relative to the tree. */
254
+ name: string;
255
+ /** Canonical Git mode. */
256
+ mode: string;
257
+ /** SHA-1 object ID. */
258
+ hash: string;
259
+ /** Git object type; executable and symlink entries are blobs distinguished by mode. */
260
+ type: "blob" | "tree" | "commit";
261
+ }>;
262
+ /** Smart-HTTP request; the host supplies and keeps the provider credential. */
263
+ export type GitExchangeRequest = Readonly<{
264
+ /** Git upload-pack (read) or receive-pack (write). */
265
+ service: "upload-pack" | "receive-pack";
266
+ /** Advertisement or data exchange phase. */
267
+ phase: "advertise" | "exchange";
268
+ /** Request bytes for exchange, or null for advertisement; bounded by the host. */
269
+ body: Uint8Array | null;
270
+ /** Protocol headers; the host never trusts incoming authorization headers. */
271
+ headers: Readonly<Record<string, string>>;
272
+ }>;
273
+ /** Credential-free RPC response; host adapters own stream conversion and byte bounds. */
274
+ export type GitExchangeResponse = Readonly<{
275
+ /** Provider HTTP status. */
276
+ status: number;
277
+ /** Protocol response headers, without host credentials. */
278
+ headers: Readonly<Record<string, string>>;
279
+ /** Git protocol response bytes. */
280
+ body: Uint8Array;
281
+ }>;
282
+ /** Installation-scoped GIT backend binding; approved operations and actor grants bound every call. */
283
+ export type GitBinding = Readonly<{
284
+ /** Create a repository in this installation. */
285
+ create(name: string, options?: {
286
+ description?: string;
287
+ defaultBranch?: string;
288
+ }): Promise<GitRepositoryInfo>;
289
+ /**
290
+ * Fork another repository in this installation, waiting for it to serve
291
+ * reads. When `target` already exists the host answers with that
292
+ * repository instead; callers compare its `source` before adopting it.
293
+ */
294
+ fork(source: string, target: string, options?: {
295
+ description?: string;
296
+ }): Promise<GitRepositoryInfo>;
297
+ /** Return the host-issued clone URL for this installation repository; authentication stays with the host. */
298
+ cloneUrl(name: string): Promise<string>;
299
+ /** Read repository metadata, or null when missing. */
300
+ info(name: string): Promise<GitRepositoryInfo | null>;
301
+ /** Delete a repository in this installation. */
302
+ delete(name: string): Promise<boolean>;
303
+ /** Read first-parent history, newest first. */
304
+ log(name: string, options: {
305
+ ref: string;
306
+ limit?: number;
307
+ offset?: number;
308
+ }): Promise<GitCommit[]>;
309
+ /** Read commit metadata, or null when missing. */
310
+ readCommit(name: string, hash: string): Promise<GitCommit | null>;
311
+ /** Read tree children, or null when missing. */
312
+ readTree(name: string, hash: string): Promise<GitTreeEntry[] | null>;
313
+ /** Read a blob bounded to 32 MiB, or null when missing. */
314
+ readBlob(name: string, hash: string): Promise<Uint8Array | null>;
315
+ /** Read advertised ref names and object IDs. */
316
+ refs(name: string): Promise<{
317
+ name: string;
318
+ hash: string;
319
+ }[]>;
320
+ /** Exchange Git bytes; receive-pack requires both exchange and write approval. */
321
+ exchange(name: string, request: GitExchangeRequest): Promise<GitExchangeResponse>;
322
+ }>;