@ref0/sdk 0.6.0 → 0.7.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/README.md CHANGED
@@ -181,7 +181,7 @@ export default workflow({
181
181
 
182
182
  `ask.run` is a step of its own. It waits for `{ key, by, via, at }`. At its deadline it returns the lean with `via: 'deadline'` and no `by`. It offers two to five answers, and a run uses each ask key once. A refused or withdrawn ask throws `AskRefused`.
183
183
 
184
- `passkey.run` is also a step of its own. Only the person in their approving browser can answer yes with their passkey. The result has `approved`, `at` and, when someone answered, `by`. A deadline answers no. `from` can also name `{ person: 'mo' }` or `{ permission: 'deploy' }`, with `person` or `permission` in `permissions.ask`. Agents have no passkey.
184
+ `passkey.run` is also a step of its own. Only the person in their approving browser can answer yes with their passkey. The result has `approved`, `at` and, when someone answered, `by`. A deadline answers no. `from` can also name someone else, `{ person: 'pip' }` or `{ permission: 'deploy' }`, with `person` or `permission` in `permissions.ask`. Someone else is never the run's accountable person: naming Mo here, or a permission only Mo holds, throws `PasskeyRequestRefused` with `self`. Agents have no passkey.
185
185
 
186
186
  Call both leaves outside `step.do` callbacks. Each request spends from the workflow's `asks` budget. Deadlines range from a minute to a day, bounded by the run's remaining day. A called workflow parses its input with one `z.object` and returns JSON to its caller.
187
187
 
@@ -248,7 +248,7 @@ The gate in story 1 takes local results with `local(unit())` and `passkey.check(
248
248
 
249
249
  The newest finished local run counts unless a ref0 failure stands. A newer local run replaces an earlier one, and a newer ref0 pass counts instead. A ref0 failure stands until an admin overrides it, even if a later run passes.
250
250
 
251
- `passkey.check` waits for the person behind the counted run to say yes over its result with their passkey. For a local run, that's the signer's person. For ref0's run, it's the version's accountable person. `{ from }` asks someone else, as in `passkey.check(local(e2e()), { from: { person: 'mo' } })`. The statement names the check-run identity, conclusion and outputs' hash. A newer counted run needs a new yes.
251
+ `passkey.check` waits for the person behind the counted run to say yes over its result with their passkey. For a local run, that's the signer's person. For ref0's run, it's the version's accountable person. `{ from }` asks someone else, as in `passkey.check(local(e2e()), { from: { person: 'mo' } })`. Someone else is never the person behind the run: if Mo ran it, or only Mo holds the permission named, ref0 refuses the request at once, and the check needs an admin's override. The statement names the check-run identity, conclusion and outputs' hash. A newer counted run needs a new yes.
252
252
 
253
253
  When ref0 runs the same check-run identity as a signed success and it fails twice, the signer stops answering that check. For `local`, ref0 revokes the attachment. For `passkey.check`, it revokes the person whose yes stood over the result. An admin restores the signer with `ref0 checks signers restore`, using `--person` for a person. The floor's needs and the queue's tip take only ref0's runs.
254
254
 
@@ -1,4 +1,4 @@
1
- import { $t as WorkflowCallRefusal, An as WorkflowStartState, Cn as WorkflowPasskeyState, Ct as SandboxPushAnswer, D as ConnectionCallAnswer, Dn as WorkflowPullRequestOpen, E as ConnectionCall, En as WorkflowPullRequestAnswer, Gt as WorkflowActionAnswer, Jt as WorkflowAskClosed, L as EventRunInput, Lt as ThreadStage, Mn as WorkflowThreadStart, Nn as WorkflowTrigger, Nt as StartActor$1, Pt as StartRun$1, Qt as WorkflowCallInput, R as ForkAnswer$1, Sn as WorkflowPasskeyRead, St as SandboxPush, V as GetIssueInput, Wt as WorkflowAction, Xt as WorkflowCallAnswer, Yt as WorkflowCall, Zt as WorkflowCallEnded, _ as CheckOwn, _n as WorkflowFilters, an as WorkflowCheckResults, b as CheckTreeEntry, bn as WorkflowPasskeyAsked, bt as SandboxOpen, cn as WorkflowCheckRunEnded, dn as WorkflowCheckStates, en as WorkflowCallRefused, fn as WorkflowCheckStatesAnswer, g as CheckOn, gn as WorkflowEvent, hn as WorkflowConnections, in as WorkflowCheckRefused, jn as WorkflowText, kn as WorkflowStartEnded, ln as WorkflowCheckStart, mn as WorkflowComment, mt as Ref0Owned, nn as WorkflowCalledStateAnswer, on as WorkflowCheckResultsAnswer, pn as WorkflowCheckWhere, rn as WorkflowCheckRefusal, sn as WorkflowCheckRun, tn as WorkflowCalledState, un as WorkflowCheckStartAnswer, v as CheckRunError, vn as WorkflowOwn, vt as SandboxExec, wn as WorkflowPermissions, xn as WorkflowPasskeyEnded, xt as SandboxOpenAnswer, y as CheckRunParams, yn as WorkflowPasskeyAsk, yt as SandboxExecAnswer, z as ForkCreate } from "./index-CJGX88qF.mjs";
1
+ import { $t as WorkflowAskClosed, A as ConnectionCallAnswer, B as EventRunInput, Cn as WorkflowOwn, Ct as SandboxExec, Dn as WorkflowPasskeyRead, Dt as SandboxPush, En as WorkflowPasskeyEnded, Et as SandboxOpenAnswer, Fn as WorkflowStartState, G as GetIssueInput, H as ForkAnswer$1, Ht as ThreadStage, In as WorkflowText, Ln as WorkflowThreadStart, Mn as WorkflowPullRequestOpen, On as WorkflowPasskeyState, Ot as SandboxPushAnswer, Pn as WorkflowStartEnded, Rn as WorkflowTrigger, Rt as StartActor$1, Sn as WorkflowFilters, Tn as WorkflowPasskeyAsked, Tt as SandboxOpen, U as ForkCreate, Xt as WorkflowActionAnswer, Yt as WorkflowAction, _ as CheckOwn, _n as WorkflowCheckStatesAnswer, an as WorkflowCallRefused, b as CheckTreeEntry, bn as WorkflowConnections, cn as WorkflowCheckRefusal, dn as WorkflowCheckResultsAnswer, en as WorkflowCall, fn as WorkflowCheckRun, g as CheckOn, gn as WorkflowCheckStates, hn as WorkflowCheckStartAnswer, in as WorkflowCallRefusal, jn as WorkflowPullRequestAnswer, k as ConnectionCall, kn as WorkflowPermissions, ln as WorkflowCheckRefused, mn as WorkflowCheckStart, nn as WorkflowCallEnded, on as WorkflowCalledState, pn as WorkflowCheckRunEnded, rn as WorkflowCallInput, sn as WorkflowCalledStateAnswer, tn as WorkflowCallAnswer, un as WorkflowCheckResults, v as CheckRunError, vn as WorkflowCheckWhere, vt as Ref0Owned, wn as WorkflowPasskeyAsk, wt as SandboxExecAnswer, xn as WorkflowEvent, y as CheckRunParams, yn as WorkflowComment, zt as StartRun$1 } from "./index-Vb8-1Zk-.mjs";
2
2
  import { z } from "zod";
3
3
  //#region src/needs.d.ts
4
4
  /**
@@ -671,4 +671,4 @@ interface Browser {
671
671
  }
672
672
  //#endregion
673
673
  export { StartActor as $, ForkOptions as A, WorkflowContext as B, Comment as C, EventWorkflow as D, EventOf as E, StepConfig as F, CalledWorkflow as G, text as H, StepContext as I, TreeEntry as J, JsonValue as K, ThreadStart as L, PullRequestAnswer as M, PullRequestOptions as N, EventWorkflowSpec as O, Ref0Actions as P, Refusal as Q, WaitType as R, CheckRunEnded as S, Duration as T, workflow as U, WorkflowStep as V, CalledRunFailed as W, Allow as X, TreeRead as Y, CalledRun as Z, ActionAnswer as _, CheckRunOptions as a, allow as at, CalledContext as b, CheckRunResult as c, Need as ct, OneOfValues as d, StartContext as et, OutputResult as f, oneOf as g, check as h, CheckResult as i, StartRun as it, NeedAddOptions as j, ForkAnswer as k, CheckSpec as l, Step as m, Check as n, StartOutput as nt, CheckRunReference as o, refuse as ot, OutputSchema as p, Tree as q, CheckContext as r, StartRule as rt, CheckRunRefused as s, CheckNeed as st, Browser as t, StartItem as tt, DurationText as u, CallAnswer as v, ConnectionsOf as w, CalledWorkflowSpec as x, CallEnded as y, WaitedEvent as z };
674
- //# sourceMappingURL=browse-DHgV6DTF.d.mts.map
674
+ //# sourceMappingURL=browse-CLwrVDwR.d.mts.map
@@ -1,4 +1,4 @@
1
- import { t as Browser } from "./browse-DHgV6DTF.mjs";
1
+ import { t as Browser } from "./browse-CLwrVDwR.mjs";
2
2
  import { BrowserContext, BrowserContext as BrowserContext$1, BrowserContextOptions, Locator, Page, Page as Page$1, Request, Response } from "@cloudflare/playwright";
3
3
  import { expect as expect$1 } from "@cloudflare/playwright/test";
4
4
  //#region src/browser-stub.d.ts
package/dist/client.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as OwnerThreadPage, A as ConnectionName, At as SignInDestination, Bn as isRef0Path, Bt as TrackThread, C as ConnectAgent, Dt as SentryOrg, Et as SecretHash, F as CredentialView, Fn as commandLine, Ft as StatementView, G as LiveTicketRequest, H as Harness, Hn as projectParts, I as EndpointName, In as connectEndpoint, It as ThreadId, J as MirrorChoice, K as LiveTrackName, Ln as encodeSecret, Lt as ThreadStage, M as ConsentAsked, Mt as SocketUrl, N as ConsentClient, O as ConnectionChanged, Ot as SentryRegion, P as ConsentProject, Pn as WrittenProject, Q as OwnerName, Rn as hookTokenPrefix, Rt as TrackClosed, S as ClientGranted, T as ConnectableAgent, Tn as WorkflowPreview, Tt as ScopeAction, U as ImportFailure, Un as repoNameKey, Ut as Welcome, Vn as liveSocketUrl, Vt as TypedApprovalCode, W as LiveTicket, Wn as surfaceOf, X as MirrorView, Y as MirrorEntry, Z as OwnerId, _t as RepoView, a as Api, c as ApprovalId, ct as PreviewEcho, d as ApprovalView, dt as ProjectTrackMessage, et as OwnerThreadView, f as AttachmentFailed, ft as RanOf, gt as RepoUrl, ht as RepoName, i as AgentView, it as PasskeyCreationOptions, j as ConnectionView, jt as SignedIn, k as ConnectionKind, kt as SentryToken, l as ApprovalPreview, lt as PreviewUnavailable, m as Authorization, n as AgentPermissionChoice, nt as PasskeyAsserted, o as ApiOrigin, p as AttachmentRequestView, pt as ReadEvent, q as MachineConnected, r as AgentPermissionSetting, rt as PasskeyCreated, s as ApprovalAnswer, st as PasskeyRequestOptions, t as AgentHandle, tt as OwnerTrackMessage, u as ApprovalState, ut as ProjectName, w as ConnectChosen, x as ClientAccess, zn as hookUrl, zt as TrackSession } from "./index-CJGX88qF.mjs";
1
+ import { $ as MirrorEntry, An as WorkflowPreview, At as ScopeAction, Bn as commandLine, Bt as StatementView, C as ConnectAgent, D as ConnectOptions, E as ConnectFolderOption, F as ConsentAsked, Ft as SignInDestination, Gn as isRef0Path, Gt as TrackThread, Hn as encodeSecret, Ht as ThreadStage, I as ConsentClient, It as SignedIn, J as LiveTicket, Jn as repoNameKey, Jt as Welcome, K as Harness, Kn as liveSocketUrl, Kt as TypedApprovalCode, L as ConsentProject, Lt as SocketUrl, M as ConnectionKind, Mt as SentryOrg, N as ConnectionName, Nt as SentryRegion, O as ConnectableAgent, P as ConnectionView, Pt as SentryToken, Q as MirrorChoice, R as CredentialView, S as ClientGranted, St as RequestFolder, T as ConnectFolderChoices, Un as hookTokenPrefix, Ut as TrackClosed, V as FoldersConnected, Vn as connectEndpoint, Vt as ThreadId, Wn as hookUrl, Wt as TrackSession, X as LiveTrackName, Y as LiveTicketRequest, Yn as surfaceOf, Z as MachineConnected, _t as ReadEvent, a as Api, at as OwnerTrackMessage, bt as RepoUrl, c as ApprovalId, ct as PasskeyCreationOptions, d as ApprovalView, dt as PasskeyRequestOptions, et as MirrorView, f as AttachmentFailed, ft as PreviewEcho, gt as RanOf, ht as ProjectTrackMessage, i as AgentView, it as OwnerThreadView, j as ConnectionChanged, jt as SecretHash, l as ApprovalPreview, m as Authorization, mt as ProjectName, n as AgentPermissionChoice, nt as OwnerName, o as ApiOrigin, ot as PasskeyAsserted, p as AttachmentRequestView, pt as PreviewUnavailable, q as ImportFailure, qn as projectParts, r as AgentPermissionSetting, rt as OwnerThreadPage, s as ApprovalAnswer, st as PasskeyCreated, t as AgentHandle, tt as OwnerId, u as ApprovalState, w as ConnectChosen, x as ClientAccess, xt as RepoView, yt as RepoName, z as EndpointName, zn as WrittenProject } from "./index-Vb8-1Zk-.mjs";
2
2
  import { Effect, Layer, Option, Redacted, Schema, Stream } from "effect";
3
3
  import { HttpApi, HttpApiClient, HttpApiGroup, HttpApiMiddleware } from "effect/http-api";
4
4
  import { HttpBody, HttpClient } from "effect/http";
@@ -90,5 +90,5 @@ export declare const startGitHubSignIn: (landing: {
90
90
  */
91
91
  export declare const signOut: (origin?: ApiOrigin) => Effect.Effect<void, import("effect/http/HttpClientError").HttpClientError, HttpClient.HttpClient>;
92
92
  //#endregion
93
- export { AgentHandle, type AgentPermissionChoice, type AgentPermissionSetting, type AgentView, ApiOrigin, type ApprovalAnswer, type ApprovalId, type ApprovalPreview, type ApprovalState, type ApprovalView, AttachmentFailed, type AttachmentRequestView, ClientAccess, ClientGranted, type ConnectAgent, type ConnectChosen, type ConnectableAgent, ConnectionChanged, ConnectionKind, ConnectionName, type ConnectionView, type ConsentAsked, type ConsentClient, ConsentProject, type CredentialView, type Harness, type ImportFailure, type LiveTicket, type LiveTicketRequest, LiveTrackName, MachineConnected, type MirrorChoice, type MirrorEntry, type MirrorView, type OwnerId, OwnerName, type OwnerThreadPage, type OwnerThreadView, OwnerTrackMessage, PasskeyAsserted, PasskeyCreated, type PasskeyCreationOptions, type PasskeyRequestOptions, type PreviewEcho, PreviewUnavailable, ProjectName, ProjectTrackMessage, type ReadEvent, type Ref0Client, RepoName, RepoUrl, type RepoView, type ScopeAction, SecretHash, SentryOrg, SentryRegion, SentryToken, type SettledApproval, SignInDestination, type StatementView, ThreadId, ThreadStage, type TrackClosed, type TrackSession, type TrackThread, TypedApprovalCode, type Welcome, WorkflowPreview, WrittenProject, commandLine, connectEndpoint, encodeSecret, hookTokenPrefix, hookUrl, isRef0Path, liveSocketUrl, projectParts, repoNameKey, surfaceOf };
93
+ export { AgentHandle, type AgentPermissionChoice, type AgentPermissionSetting, type AgentView, ApiOrigin, type ApprovalAnswer, type ApprovalId, type ApprovalPreview, type ApprovalState, type ApprovalView, AttachmentFailed, AttachmentRequestView, ClientAccess, ClientGranted, type ConnectAgent, type ConnectChosen, type ConnectFolderChoices, type ConnectFolderOption, type ConnectOptions, type ConnectableAgent, ConnectionChanged, ConnectionKind, ConnectionName, type ConnectionView, type ConsentAsked, type ConsentClient, ConsentProject, type CredentialView, FoldersConnected, type Harness, type ImportFailure, type LiveTicket, type LiveTicketRequest, LiveTrackName, MachineConnected, type MirrorChoice, type MirrorEntry, type MirrorView, type OwnerId, OwnerName, type OwnerThreadPage, type OwnerThreadView, OwnerTrackMessage, PasskeyAsserted, PasskeyCreated, type PasskeyCreationOptions, type PasskeyRequestOptions, type PreviewEcho, PreviewUnavailable, ProjectName, ProjectTrackMessage, type ReadEvent, type Ref0Client, RepoName, RepoUrl, type RepoView, type RequestFolder, type ScopeAction, SecretHash, SentryOrg, SentryRegion, SentryToken, type SettledApproval, SignInDestination, type StatementView, ThreadId, ThreadStage, type TrackClosed, type TrackSession, type TrackThread, TypedApprovalCode, type Welcome, WorkflowPreview, WrittenProject, commandLine, connectEndpoint, encodeSecret, hookTokenPrefix, hookUrl, isRef0Path, liveSocketUrl, projectParts, repoNameKey, surfaceOf };
94
94
  //# sourceMappingURL=client.d.mts.map
package/dist/client.mjs CHANGED
@@ -1266,7 +1266,9 @@ const FindingRef = Schema.Struct({
1266
1266
  * Who a passkey request asks: the accountable person; a person, by their name; or anyone holding
1267
1267
  * one of the repo's permissions, the first of whom to answer decides. Until a permission's holders
1268
1268
  * are kept, they're its owner's admins. A workflow run's `passkey.run` asks its run's accountable
1269
- * person; a gate's `passkey.check` asks the person behind the run that meets its need.
1269
+ * person; a gate's `passkey.check` asks the person behind the run that meets its need. A person or
1270
+ * a permission is someone else, a second pair of eyes, so the person `'accountable'` would ask
1271
+ * never answers it: a request with nobody else to ask is refused.
1270
1272
  */
1271
1273
  const PasskeyFrom = Schema.Union([
1272
1274
  Schema.Literal("accountable"),
@@ -6421,35 +6423,46 @@ var PasskeyRefused = class extends Schema.TaggedError()("PasskeyRefused", { next
6421
6423
  const MachineName = Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(64));
6422
6424
  /** The harness a machine says it connects for, never proof of what it runs. */
6423
6425
  const ConnectHarness = Schema.Literals(["claude-code", "codex"]);
6424
- /**
6425
- * A machine asks with no owner and sends hashes of its grant, collecting and link secrets.
6426
- * The optional callback names only a loopback port and a random state segment, never a host.
6427
- */
6426
+ /** The machine's loopback listener; no caller may choose its host. */
6427
+ const AttachmentCallback = Schema.Struct({
6428
+ port: Schema.Int.check(Schema.isBetween({
6429
+ minimum: 1024,
6430
+ maximum: 65535
6431
+ })),
6432
+ state: Schema.String.check(Schema.isPattern(/^[A-Za-z0-9_-]{22}$/))
6433
+ });
6434
+ /** A config folder's path, as the machine shows it, never proof of its location. */
6435
+ const ConfigFolderPath = Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(200), Schema.isPattern(/^[^\p{C}\p{Zl}\p{Zp}]+$/u));
6436
+ const uniqueFolderPaths = Schema.makeFilter((folders) => new Set(folders.map((folder) => folder.path)).size === folders.length, { expected: "unique config folder paths" });
6437
+ const RequestFolder = Schema.Struct({
6438
+ path: ConfigFolderPath,
6439
+ harness: ConnectHarness,
6440
+ secretHash: SecretHash,
6441
+ replaces: Schema.optionalKey(TokenId)
6442
+ });
6443
+ /** One to eight config folders, each with its own grant secret. */
6428
6444
  const RequestAttachment = Schema.Struct({
6429
6445
  machine: MachineId,
6430
6446
  machineName: MachineName,
6431
- harness: Schema.optionalKey(ConnectHarness),
6432
- secretHash: SecretHash,
6447
+ folders: Schema.Array(RequestFolder).check(Schema.isMinLength(1), Schema.isMaxLength(8), uniqueFolderPaths),
6433
6448
  collectHash: SecretHash,
6434
6449
  linkHash: SecretHash,
6435
- callback: Schema.optionalKey(Schema.Struct({
6436
- port: Schema.Int.check(Schema.isBetween({
6437
- minimum: 1024,
6438
- maximum: 65535
6439
- })),
6440
- state: Schema.String.check(Schema.isPattern(/^[A-Za-z0-9_-]{22}$/))
6441
- }))
6450
+ callback: Schema.optionalKey(AttachmentCallback)
6442
6451
  });
6443
6452
  /** An attachment request, as its person reads it once they type its code. */
6444
6453
  const AttachmentRequestView = Schema.Struct({
6445
6454
  approval: ApprovalId,
6446
6455
  /** The machine's own word for itself, never fact. */
6447
6456
  machineName: MachineName,
6448
- /** The harness the machine says it uses, never fact. */
6449
- harness: Schema.optionalKey(ConnectHarness),
6457
+ folders: Schema.Array(Schema.Struct({
6458
+ path: ConfigFolderPath,
6459
+ harness: ConnectHarness,
6460
+ replaces: Schema.optionalKey(TokenId)
6461
+ })),
6450
6462
  askedFrom: Schema.optionalKey(Schema.String),
6451
6463
  askedAt: Timestamp,
6452
- expiresAt: Timestamp
6464
+ expiresAt: Timestamp,
6465
+ callback: Schema.optionalKey(AttachmentCallback)
6453
6466
  });
6454
6467
  /**
6455
6468
  * What its answerer chooses to connect a machine's request to: one of the person's own agents,
@@ -6473,6 +6486,16 @@ const ConnectOrganization = Schema.Struct({
6473
6486
  organization: OrgId,
6474
6487
  name: OwnerName
6475
6488
  });
6489
+ /** Whether admission replaced a live host grant, or skipped one that no longer belongs here. */
6490
+ const GrantReplacement = Schema.Struct({
6491
+ grant: TokenId,
6492
+ state: Schema.Literals([
6493
+ "replaces",
6494
+ "revoked",
6495
+ "skipped"
6496
+ ]),
6497
+ attachedAt: Schema.optionalKey(Timestamp)
6498
+ });
6476
6499
  /**
6477
6500
  * What a yes would connect the machine to, as options resolved the choice: the agent, or none
6478
6501
  * yet, to make with the handle; and each organization its attachment is authorized in.
@@ -6480,22 +6503,32 @@ const ConnectOrganization = Schema.Struct({
6480
6503
  const ConnectChosen = Schema.Struct({
6481
6504
  agent: Schema.optionalKey(AgentRef),
6482
6505
  handle: AgentHandle,
6483
- organizations: Schema.Array(ConnectOrganization)
6506
+ organizations: Schema.Array(ConnectOrganization),
6507
+ replacement: Schema.optionalKey(GrantReplacement)
6484
6508
  });
6485
- /**
6486
- * A machine's request, as its answerer chooses what it connects to. Without a choice: the
6487
- * request and the person's agents that are on, and nothing chosen for them. With one: the
6488
- * request, what the choice resolved to, and the passkey's options, whose challenge signs over
6489
- * the connect it would run.
6490
- */
6491
- const ConnectOptions = Schema.Union([Schema.Struct({
6492
- request: AttachmentRequestView,
6493
- agents: Schema.Array(ConnectableAgent)
6509
+ /** A complete choice: name every folder once, leaving at least one in. */
6510
+ const ConnectFolderChoice = Schema.Union([Schema.Struct({
6511
+ path: ConfigFolderPath,
6512
+ excluded: Schema.Literal(true)
6494
6513
  }), Schema.Struct({
6514
+ path: ConfigFolderPath,
6515
+ agent: ConnectAgent
6516
+ })]);
6517
+ const ConnectFolderChoices = Schema.Array(ConnectFolderChoice).check(Schema.isMinLength(1), Schema.isMaxLength(8), uniqueFolderPaths);
6518
+ const ConnectFolderOption = Schema.Union([Schema.Struct({
6519
+ path: ConfigFolderPath,
6520
+ excluded: Schema.Literal(true)
6521
+ }), Schema.Struct({
6522
+ path: ConfigFolderPath,
6523
+ connect: ConnectChosen
6524
+ })]);
6525
+ /** Defaults and explicit choices both resolve the entire request and sign one challenge. */
6526
+ const ConnectOptions = Schema.Struct({
6495
6527
  request: AttachmentRequestView,
6496
- connect: ConnectChosen,
6528
+ agents: Schema.Array(ConnectableAgent),
6529
+ folders: Schema.Array(ConnectFolderOption),
6497
6530
  passkey: PasskeyRequestOptions
6498
- })]);
6531
+ });
6499
6532
  /** Why connecting connected nothing, said for the person. */
6500
6533
  const AttachmentFailure = Schema.Struct({
6501
6534
  reason: Schema.Literals([
@@ -6523,11 +6556,9 @@ const RequestOrganization = Schema.Struct({
6523
6556
  ])
6524
6557
  });
6525
6558
  /**
6526
- * Where a machine's request stands, for the machine that asked, by its collecting secret: waiting,
6527
- * or how it ended. Every answer but waiting is final, but a connect nobody confirmed 10 minutes
6528
- * after it connected fails `not confirmed` once ref0 takes its grant to revoke it. Connected
6529
- * names the owner by its name, and the host grant, whose token the machine makes from its ID and
6530
- * the grant's secret.
6559
+ * The result collected with the machine's two proofs: each included folder's identity and grant,
6560
+ * its agent's owner name and organizations, and excluded paths. Confirmation checks each saved
6561
+ * grant's live deadline in the Owner DO.
6531
6562
  */
6532
6563
  const RequestState = Schema.Union([
6533
6564
  Schema.Struct({
@@ -6537,20 +6568,30 @@ const RequestState = Schema.Union([
6537
6568
  Schema.Struct({
6538
6569
  state: Schema.Literal("connected"),
6539
6570
  owner: OwnerName,
6540
- agent: AgentRef,
6541
- handle: AgentHandle,
6542
- credential: CredentialRef,
6543
- organizations: Schema.Array(RequestOrganization)
6571
+ folders: Schema.Array(Schema.Struct({
6572
+ path: ConfigFolderPath,
6573
+ owner: OwnerName,
6574
+ ...MachineConnected.fields,
6575
+ organizations: Schema.Array(RequestOrganization),
6576
+ replacement: Schema.optionalKey(GrantReplacement)
6577
+ })),
6578
+ excluded: Schema.Array(ConfigFolderPath)
6544
6579
  }),
6545
6580
  Schema.Struct({ state: Schema.Literal("refused") }),
6546
6581
  Schema.Struct({ state: Schema.Literal("aborted") }),
6547
6582
  Schema.Struct({ state: Schema.Literal("expired") }),
6548
6583
  Schema.Struct({
6549
6584
  state: Schema.Literal("failed"),
6550
- reason: Schema.Literals([...AttachmentFailure.fields.reason.literals, "not confirmed"]),
6585
+ reason: AttachmentFailure.fields.reason,
6551
6586
  nextStep: Schema.String
6552
6587
  })
6553
6588
  ]);
6589
+ /** The grant IDs saved by this terminal, each belonging to the same admission. */
6590
+ const SavedMachineGrants = Schema.Array(TokenId).check(Schema.isMinLength(1), Schema.isMaxLength(8), Schema.isUnique());
6591
+ Schema.Struct({
6592
+ approval: ApprovalId,
6593
+ grants: SavedMachineGrants
6594
+ });
6554
6595
  /**
6555
6596
  * The machine saying it saved the grant it collected: confirmed, the same again, or not, once ref0
6556
6597
  * has taken the grant to revoke it, and the machine deletes what it saved.
@@ -6583,21 +6624,34 @@ const AuthorizeIn = Schema.Struct({
6583
6624
  organization: OrgId,
6584
6625
  targetGeneration: TargetGeneration
6585
6626
  });
6586
- /** What every connect names: the agent, the machine and its host grant, and what it was bound to. */
6587
- const connectFields = {
6627
+ /** One folder admitted under the request's machine and approving browser. */
6628
+ const ConnectFolderCommand = Schema.Struct({
6629
+ path: ConfigFolderPath,
6588
6630
  agent: AttachmentAgent,
6589
- machine: MachineId,
6590
- machineName: MachineName,
6591
6631
  token: TokenId,
6592
6632
  secretHash: SecretHash,
6593
- browserSession: TokenId,
6594
- personGeneration: Generation,
6633
+ replaces: Schema.optionalKey(TokenId),
6595
6634
  authorizeIn: Schema.Array(AuthorizeIn)
6596
- };
6635
+ });
6597
6636
  Schema.Struct({
6598
6637
  request: ApprovalId,
6599
- ...connectFields
6638
+ machine: MachineId,
6639
+ machineName: MachineName,
6640
+ browserSession: TokenId,
6641
+ personGeneration: Generation,
6642
+ folders: Schema.Array(ConnectFolderCommand).check(Schema.isMinLength(1), Schema.isMaxLength(8), uniqueFolderPaths),
6643
+ excluded: Schema.Array(ConfigFolderPath).check(Schema.isMaxLength(7), Schema.isUnique())
6644
+ });
6645
+ const FoldersConnected = Schema.Struct({
6646
+ folders: Schema.Array(Schema.Struct({
6647
+ path: ConfigFolderPath,
6648
+ ...MachineConnected.fields,
6649
+ replacement: Schema.optionalKey(GrantReplacement)
6650
+ })),
6651
+ excluded: Schema.Array(ConfigFolderPath)
6600
6652
  });
6653
+ Schema.Array(GrantReplacement);
6654
+ Schema.Array(TokenId).check(Schema.isMaxLength(8));
6601
6655
  /** An attachment that isn't there, or isn't the caller's, answers the same. */
6602
6656
  var AttachmentNotFound = class extends Schema.TaggedError()("AttachmentNotFound", { nextStep: Schema.String }, { httpApiStatus: 404 }) {};
6603
6657
  /** Connecting connected nothing, and why: what an attachment's approval came to instead. */
@@ -6779,7 +6833,7 @@ const FindApproval = Schema.Union([Schema.Struct({ code: TypedApprovalCode }), S
6779
6833
  */
6780
6834
  const ApprovalOptionsRequest = Schema.Struct({
6781
6835
  code: Schema.optionalKey(TypedApprovalCode),
6782
- agent: Schema.optionalKey(ConnectAgent)
6836
+ folders: Schema.optionalKey(ConnectFolderChoices)
6783
6837
  });
6784
6838
  /**
6785
6839
  * An answer: yes, with the passkey, or no. For an agent's ask, each answer can set the owner's
@@ -6832,7 +6886,11 @@ const ApprovalState = Schema.Union([
6832
6886
  state: Schema.Literal("waiting"),
6833
6887
  expiresAt: Timestamp
6834
6888
  }),
6835
- Schema.Struct({ state: Schema.Literal("approved") }),
6889
+ Schema.Struct({
6890
+ state: Schema.Literal("approved"),
6891
+ /** A machine's answering browser may forget its saved answer once the terminal kept it. */
6892
+ collected: Schema.optionalKey(Schema.Literal(true))
6893
+ }),
6836
6894
  Schema.Struct({ state: Schema.Literal("refused") }),
6837
6895
  Schema.Struct({ state: Schema.Literal("expired") }),
6838
6896
  Schema.Struct({
@@ -11787,10 +11845,10 @@ const GateInPlaceView = Schema.Struct({
11787
11845
  /**
11788
11846
  * One `from`'s yes over the run that counts for a part that needs one (L2), as `passkey.check`
11789
11847
  * asks: `asked`, waiting, of `asked` when it's one person; `yes`, by whom and when; `no`;
11790
- * `expired`, its day passed unanswered; `refused`, the person it names can't be asked; or
11791
- * `revoked`, a yes whose answerer a miss revoked since, until an admin restores them. A local
11792
- * run's no or day passing waits for a newer local run; a ref0 run's, or a refusal, leaves the
11793
- * part with no yes, until an admin overrides it.
11848
+ * `expired`, its day passed unanswered; `refused`, asking nobody, `why`; or `revoked`, a yes whose
11849
+ * answerer a miss revoked since, until an admin restores them. A local run's no or day passing
11850
+ * waits for a newer local run; a ref0 run's, or a refusal, leaves the part with no yes, until an
11851
+ * admin overrides it.
11794
11852
  */
11795
11853
  const GatePartYes = Schema.Struct({
11796
11854
  from: PasskeyFrom,
@@ -11802,6 +11860,12 @@ const GatePartYes = Schema.Struct({
11802
11860
  "refused",
11803
11861
  "revoked"
11804
11862
  ]),
11863
+ /**
11864
+ * Why a request was refused: `target`, nobody it names can be asked, a person who isn't there
11865
+ * or can't see the pull request's thread; or `self`, it names the person behind the run, or a
11866
+ * permission only they hold, who can't be the second pair of eyes over their own run.
11867
+ */
11868
+ why: Schema.optionalKey(Schema.Literals(["target", "self"])),
11805
11869
  asked: Schema.optionalKey(PersonId),
11806
11870
  by: Schema.optionalKey(OwnerName),
11807
11871
  at: Schema.optionalKey(Schema.DateTimeUtcFromMillis)
@@ -14969,7 +15033,10 @@ var MachineAttachmentsGroup = class extends HttpApiGroup.make("machineAttachment
14969
15033
  error: [AttachmentNotFound, AuthorityUnavailable]
14970
15034
  }).middleware(ApprovalSecret), HttpApiEndpoint.post("confirm", "/v1/attachments/requests/:approval/collected", {
14971
15035
  params: { approval: ApprovalId },
14972
- payload: Schema.Struct({ answerCode: Schema.optionalKey(Schema.String.check(Schema.isMaxLength(64))) }),
15036
+ payload: Schema.Struct({
15037
+ grants: SavedMachineGrants,
15038
+ answerCode: Schema.optionalKey(Schema.String.check(Schema.isMaxLength(64)))
15039
+ }),
14973
15040
  headers: idempotency,
14974
15041
  success: RequestConfirmed,
14975
15042
  error: [AttachmentNotFound, AuthorityUnavailable]
@@ -17978,7 +18045,7 @@ HttpApi.reflect(Api, {
17978
18045
  * leaves out only `ApprovalNeeded`, at `202`.
17979
18046
  */
17980
18047
  const schemasOf = (name) => Option.fromNullishOr(reflected.get(name));
17981
- Schema.toCodecJson(MachineConnected), Schema.toCodecJson(AttachmentFailed);
18048
+ Schema.toCodecJson(FoldersConnected), Schema.toCodecJson(AttachmentFailed);
17982
18049
  const isEndpointName = (name) => name in surfaces;
17983
18050
  const encodeJson = Schema.encodeEffect(Schema.fromJsonString(Schema.Json));
17984
18051
  const decodeJson = Schema.decodeUnknownEffect(Schema.Json);
@@ -18247,6 +18314,6 @@ const signOut = (origin) => Effect.gen(function* () {
18247
18314
  yield* client.execute(HttpClientRequest.make(method)(path, { body: HttpBody.jsonUnsafe({}) }));
18248
18315
  });
18249
18316
  //#endregion
18250
- export { AgentHandle, ApiOrigin, AttachmentFailed, ClientAccess, ClientGranted, ConnectionChanged, ConnectionKind, ConnectionName, ConsentProject, LiveTrackName, MachineConnected, OwnerName, OwnerTrackMessage, PasskeyAsserted, PasskeyCreated, PreviewUnavailable, ProjectName, ProjectTrackMessage, RepoName, RepoUrl, SecretHash, SentryOrg, SentryRegion, SentryToken, SignInDestination, ThreadId, ThreadStage, TypedApprovalCode, WorkflowPreview, WrittenProject, anonymousCredential, bearerCredential, browserCredential, commandLine, connectEndpoint, encodeSecret, fetchTransport, followApproval, hookTokenPrefix, hookUrl, isRef0Path, liveMessages, liveSocketUrl, newRequestId, projectParts, ref0Client, repoNameKey, settledOf, signOut, startGitHubSignIn, surfaceOf };
18317
+ export { AgentHandle, ApiOrigin, AttachmentFailed, AttachmentRequestView, ClientAccess, ClientGranted, ConnectionChanged, ConnectionKind, ConnectionName, ConsentProject, FoldersConnected, LiveTrackName, MachineConnected, OwnerName, OwnerTrackMessage, PasskeyAsserted, PasskeyCreated, PreviewUnavailable, ProjectName, ProjectTrackMessage, RepoName, RepoUrl, SecretHash, SentryOrg, SentryRegion, SentryToken, SignInDestination, ThreadId, ThreadStage, TypedApprovalCode, WorkflowPreview, WrittenProject, anonymousCredential, bearerCredential, browserCredential, commandLine, connectEndpoint, encodeSecret, fetchTransport, followApproval, hookTokenPrefix, hookUrl, isRef0Path, liveMessages, liveSocketUrl, newRequestId, projectParts, ref0Client, repoNameKey, settledOf, signOut, startGitHubSignIn, surfaceOf };
18251
18318
 
18252
18319
  //# sourceMappingURL=client.mjs.map