toolroll 0.9.62 → 0.9.65
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/CHANGELOG.md +80 -0
- package/README.md +66 -8
- package/dist/acp-agents.d.ts +43 -0
- package/dist/acp-agents.js +62 -0
- package/dist/acp-attest.d.ts +44 -0
- package/dist/acp-attest.js +269 -0
- package/dist/acp-check.d.ts +28 -0
- package/dist/acp-check.js +410 -0
- package/dist/acp-client.d.ts +163 -0
- package/dist/acp-client.js +738 -0
- package/dist/acp-inspect.d.ts +23 -0
- package/dist/acp-inspect.js +109 -0
- package/dist/agent-board.d.ts +19 -6
- package/dist/agent-board.js +30 -9
- package/dist/agent-fence.d.ts +203 -10
- package/dist/agent-fence.js +623 -41
- package/dist/agent-pulse.js +9 -2
- package/dist/agent-state-words.d.ts +19 -0
- package/dist/agent-state-words.js +20 -0
- package/dist/agent-state.d.ts +65 -0
- package/dist/agent-state.js +229 -0
- package/dist/agentconfig.js +36 -13
- package/dist/agents-board.d.ts +34 -2
- package/dist/agents-board.js +110 -1
- package/dist/approval-rules-ui.js +2 -2
- package/dist/assignment-delivery.d.ts +14 -0
- package/dist/assignment-delivery.js +13 -0
- package/dist/assignment.js +13 -0
- package/dist/attest.js +7 -0
- package/dist/backup-ui.js +2 -2
- package/dist/browser/THIRD_PARTY_NOTICES.txt +48 -0
- package/dist/browser/terminal.css +37 -0
- package/dist/browser/terminal.js +117 -0
- package/dist/browser/workspace.css +2 -2
- package/dist/browser/workspace.js +42 -38
- package/dist/browser-shell.js +6 -3
- package/dist/browser-workspace.d.ts +263 -1
- package/dist/browser-workspace.js +60 -0
- package/dist/builder.d.ts +6 -1
- package/dist/builder.js +34 -13
- package/dist/chat-actions.d.ts +13 -1
- package/dist/chat-actions.js +199 -17
- package/dist/chat-ask.d.ts +4 -0
- package/dist/chat-ask.js +14 -0
- package/dist/chat-channel.js +20 -0
- package/dist/chat-continuity.js +5 -4
- package/dist/chat-decide.d.ts +0 -14
- package/dist/chat-decide.js +4 -1
- package/dist/chat-delivery.d.ts +9 -0
- package/dist/chat-delivery.js +45 -6
- package/dist/chat-messages.d.ts +8 -0
- package/dist/chat-messages.js +36 -4
- package/dist/check-levels-ui.js +2 -2
- package/dist/check-levels.js +3 -0
- package/dist/checkout-proof.d.ts +28 -0
- package/dist/checkout-proof.js +62 -0
- package/dist/claim.d.ts +12 -0
- package/dist/claim.js +20 -1
- package/dist/cli-help.d.ts +1 -1
- package/dist/cli-help.js +5 -1
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +24 -2
- package/dist/coding-ui.js +6 -4
- package/dist/console-instance.d.ts +124 -0
- package/dist/console-instance.js +337 -0
- package/dist/contracts/chat-actions.d.ts +16 -0
- package/dist/contracts/chat-actions.js +4 -0
- package/dist/contracts/chat-content.d.ts +19 -0
- package/dist/contracts/chat-content.js +6 -0
- package/dist/contracts/cli.d.ts +8 -0
- package/dist/contracts/cli.js +3 -1
- package/dist/contracts/console-api.d.ts +30 -4
- package/dist/contracts/console-api.js +13 -4
- package/dist/contracts/flow-card.d.ts +4 -0
- package/dist/contracts/flow-card.js +3 -0
- package/dist/contracts/flow.d.ts +46 -0
- package/dist/contracts/flow.js +11 -2
- package/dist/contracts/integration-metadata.d.ts +2 -1
- package/dist/contracts/integration-metadata.js +2 -1
- package/dist/contracts/lead-tools.d.ts +92 -0
- package/dist/contracts/lead-tools.js +13 -0
- package/dist/contracts/provider.d.ts +11 -1
- package/dist/contracts/provider.js +1 -1
- package/dist/contracts/route.d.ts +76 -1
- package/dist/contracts/route.js +1 -1
- package/dist/contracts/store-json.d.ts +2 -0
- package/dist/control-setup.d.ts +1 -1
- package/dist/control-ui.js +2 -2
- package/dist/converse.d.ts +16 -0
- package/dist/converse.js +32 -4
- package/dist/demo-chat.js +4 -4
- package/dist/demo.js +2 -2
- package/dist/desktop-update-gate.js +6 -0
- package/dist/discord-chat.js +4 -1
- package/dist/dispatch.js +7 -4
- package/dist/doctor.d.ts +53 -0
- package/dist/doctor.js +427 -0
- package/dist/egress-bridge.d.ts +17 -0
- package/dist/egress-bridge.js +111 -0
- package/dist/egress.d.ts +119 -0
- package/dist/egress.js +423 -0
- package/dist/evidence-pack.d.ts +1 -1
- package/dist/evidence-pack.js +2 -2
- package/dist/exec.d.ts +81 -0
- package/dist/exec.js +368 -9
- package/dist/export-ui.js +2 -2
- package/dist/flow-code.d.ts +2 -2
- package/dist/flow-code.js +4 -15
- package/dist/flow-engine.js +35 -11
- package/dist/flow-gallery-ui.js +2 -2
- package/dist/flow-gallery.js +27 -8
- package/dist/flow-share.js +16 -5
- package/dist/flow-triggers.d.ts +84 -11
- package/dist/flow-triggers.js +554 -87
- package/dist/flow-unattended-words.d.ts +28 -0
- package/dist/flow-unattended-words.js +50 -0
- package/dist/flow-unattended.d.ts +227 -0
- package/dist/flow-unattended.js +776 -0
- package/dist/flows-cli.d.ts +28 -1
- package/dist/flows-cli.js +63 -12
- package/dist/flows-ui.d.ts +2 -3
- package/dist/flows-ui.js +56 -5
- package/dist/flows.d.ts +4 -0
- package/dist/flows.js +9 -1
- package/dist/google-mail.d.ts +1 -0
- package/dist/google-mail.js +61 -18
- package/dist/html.d.ts +9 -0
- package/dist/html.js +11 -0
- package/dist/integrations-ui.d.ts +2 -1
- package/dist/integrations-ui.js +6 -3
- package/dist/integrations.d.ts +17 -3
- package/dist/integrations.js +38 -18
- package/dist/invoke.d.ts +17 -0
- package/dist/invoke.js +510 -182
- package/dist/keys.d.ts +18 -14
- package/dist/keys.js +5 -0
- package/dist/landed-cleanup.d.ts +3 -2
- package/dist/landed-cleanup.js +12 -5
- package/dist/lead-capabilities.js +3 -2
- package/dist/lead-contract.js +2 -0
- package/dist/lead-doors.d.ts +2 -0
- package/dist/lead-doors.js +7 -0
- package/dist/lead-follow.d.ts +2 -0
- package/dist/lead-follow.js +58 -2
- package/dist/lead-progress.js +1 -0
- package/dist/lead-queue-runtime.d.ts +46 -0
- package/dist/lead-queue-runtime.js +191 -0
- package/dist/lead-queue.d.ts +104 -0
- package/dist/lead-queue.js +187 -0
- package/dist/lead-sweep.d.ts +67 -0
- package/dist/lead-sweep.js +99 -0
- package/dist/lead-tools.d.ts +22 -0
- package/dist/lead-tools.js +163 -4
- package/dist/lead.d.ts +13 -5
- package/dist/lead.js +89 -29
- package/dist/limits-ui.d.ts +8 -1
- package/dist/limits-ui.js +26 -0
- package/dist/live-bus.d.ts +8 -0
- package/dist/live-bus.js +40 -4
- package/dist/live-detail.d.ts +27 -0
- package/dist/live-detail.js +57 -0
- package/dist/live-notes.d.ts +20 -0
- package/dist/live-notes.js +47 -0
- package/dist/live-records.d.ts +140 -0
- package/dist/live-records.js +935 -0
- package/dist/live-terminal.d.ts +258 -0
- package/dist/live-terminal.js +649 -0
- package/dist/live.d.ts +38 -27
- package/dist/live.js +142 -124
- package/dist/mcp-connect.d.ts +8 -7
- package/dist/mcp-connect.js +49 -51
- package/dist/mcp-oauth.d.ts +6 -3
- package/dist/mcp-oauth.js +8 -4
- package/dist/memory-pass.js +2 -2
- package/dist/mobile-viewport.d.ts +5 -1
- package/dist/mobile-viewport.js +18 -2
- package/dist/model-catalog.js +4 -0
- package/dist/monitoring-ui.js +2 -2
- package/dist/needs-you.d.ts +1 -1
- package/dist/needs-you.js +11 -4
- package/dist/oauth-run-token.d.ts +51 -0
- package/dist/oauth-run-token.js +127 -0
- package/dist/operate.d.ts +2 -0
- package/dist/operate.js +282 -18
- package/dist/passwordless.d.ts +23 -0
- package/dist/passwordless.js +26 -0
- package/dist/peek-cli.d.ts +12 -4
- package/dist/peek-cli.js +19 -11
- package/dist/phase-routing.js +10 -3
- package/dist/plan-auto.d.ts +11 -0
- package/dist/plan-auto.js +62 -11
- package/dist/planner-source.d.ts +3 -0
- package/dist/planner-source.js +14 -0
- package/dist/planner.d.ts +2 -1
- package/dist/planner.js +7 -1
- package/dist/policy-ui.js +2 -2
- package/dist/policy.d.ts +1 -20
- package/dist/policy.js +29 -2
- package/dist/process-recovery-eligibility.d.ts +1 -1
- package/dist/project-access.d.ts +3 -0
- package/dist/project-access.js +3 -0
- package/dist/project-delete-ui.d.ts +12 -0
- package/dist/project-delete-ui.js +41 -9
- package/dist/project-delete.d.ts +3 -1
- package/dist/project-delete.js +12 -6
- package/dist/project-file.d.ts +3 -0
- package/dist/project-file.js +16 -0
- package/dist/project-memory.d.ts +3 -1
- package/dist/project-memory.js +57 -25
- package/dist/project-tools.d.ts +103 -27
- package/dist/project-tools.js +399 -100
- package/dist/provider-auth.d.ts +4 -3
- package/dist/provider-auth.js +5 -4
- package/dist/provider-connection.d.ts +2 -1
- package/dist/provider-connection.js +5 -0
- package/dist/provider-home.d.ts +22 -0
- package/dist/provider-home.js +99 -0
- package/dist/provider.d.ts +42 -5
- package/dist/provider.js +97 -19
- package/dist/pull-request-ui.js +2 -2
- package/dist/push.js +1 -1
- package/dist/quick-start.d.ts +24 -0
- package/dist/quick-start.js +127 -0
- package/dist/release.d.ts +3 -0
- package/dist/release.js +14 -8
- package/dist/remote-main.d.ts +4 -0
- package/dist/remote-main.js +3 -3
- package/dist/request-budget-ui.js +2 -2
- package/dist/result-review.d.ts +1 -1
- package/dist/result-review.js +9 -3
- package/dist/retention-ui.js +2 -2
- package/dist/retention.js +10 -1
- package/dist/run-efficiency.d.ts +73 -0
- package/dist/run-efficiency.js +228 -0
- package/dist/runner.d.ts +5 -1
- package/dist/runner.js +22 -1
- package/dist/scope.d.ts +171 -6
- package/dist/scope.js +251 -31
- package/dist/scout-net.d.ts +4 -1
- package/dist/scout-net.js +37 -12
- package/dist/scout.d.ts +20 -6
- package/dist/scout.js +27 -3
- package/dist/serve.js +258 -43
- package/dist/server/chat.d.ts +1 -1
- package/dist/server/chat.js +122 -31
- package/dist/server/chrome.d.ts +6 -1
- package/dist/server/chrome.js +18 -7
- package/dist/server/console.css +52 -38
- package/dist/server/flows.js +65 -13
- package/dist/server/guards.d.ts +1 -0
- package/dist/server/guards.js +23 -9
- package/dist/server/http.d.ts +7 -0
- package/dist/server/http.js +3 -2
- package/dist/server/live.d.ts +34 -1
- package/dist/server/live.js +39 -17
- package/dist/server/pages-assets.js +5 -0
- package/dist/server/pages.js +90 -13
- package/dist/server/people-tokens.d.ts +3 -0
- package/dist/server/people-tokens.js +55 -17
- package/dist/server/remote-hooks.js +12 -6
- package/dist/server/remote.d.ts +2 -1
- package/dist/server/remote.js +14 -5
- package/dist/server/render-chat.d.ts +12 -3
- package/dist/server/render-chat.js +47 -16
- package/dist/server/render-pages.d.ts +4 -1
- package/dist/server/render-pages.js +5 -4
- package/dist/server/render-people.d.ts +3 -2
- package/dist/server/render-people.js +3 -2
- package/dist/server/render-results.d.ts +18 -2
- package/dist/server/render-results.js +37 -28
- package/dist/server/render-settings.js +6 -5
- package/dist/server/render-tasks.d.ts +35 -10
- package/dist/server/render-tasks.js +110 -27
- package/dist/server/request-context.d.ts +2 -0
- package/dist/server/request-context.js +2 -1
- package/dist/server/route-table.d.ts +3 -0
- package/dist/server/route-table.js +49 -5
- package/dist/server/runtime.d.ts +34 -3
- package/dist/server/session.d.ts +25 -1
- package/dist/server/session.js +18 -4
- package/dist/server/settings.js +132 -13
- package/dist/server/sweeps.d.ts +4 -0
- package/dist/server/sweeps.js +58 -0
- package/dist/server/task-views.d.ts +2 -1
- package/dist/server/task-views.js +96 -6
- package/dist/server/tasks.js +320 -74
- package/dist/server/terminals.d.ts +31 -0
- package/dist/server/terminals.js +365 -0
- package/dist/setup-guide.js +3 -2
- package/dist/slack-chat.js +4 -1
- package/dist/spend-ui.js +3 -3
- package/dist/spend.js +2 -1
- package/dist/steer-capabilities.d.ts +32 -0
- package/dist/steer-capabilities.js +60 -0
- package/dist/steer-controls.d.ts +14 -0
- package/dist/steer-controls.js +36 -0
- package/dist/steer-status.js +2 -2
- package/dist/storage-sweep-child.js +3 -1
- package/dist/storage-sweep-process.d.ts +12 -5
- package/dist/storage-sweep-process.js +23 -6
- package/dist/storage-ui.js +4 -4
- package/dist/store-baseline.d.ts +1 -1
- package/dist/store-baseline.js +1 -1
- package/dist/store.d.ts +466 -19
- package/dist/store.js +1185 -63
- package/dist/subagent-desk.js +1 -1
- package/dist/subagent-tools.d.ts +1 -1
- package/dist/summary.js +3 -0
- package/dist/surface.js +6 -4
- package/dist/task-source.d.ts +58 -0
- package/dist/task-source.js +93 -0
- package/dist/team-leads.js +1 -1
- package/dist/teams-chat.js +4 -1
- package/dist/teardown-git.d.ts +14 -0
- package/dist/teardown-git.js +119 -0
- package/dist/telegram-lead.d.ts +3 -0
- package/dist/telegram-lead.js +44 -7
- package/dist/telegram.d.ts +11 -2
- package/dist/telegram.js +51 -17
- package/dist/terminal-catalog.d.ts +11 -0
- package/dist/terminal-catalog.js +129 -0
- package/dist/text-limits.d.ts +2 -0
- package/dist/text-limits.js +2 -0
- package/dist/tool-broker.d.ts +39 -0
- package/dist/tool-broker.js +370 -0
- package/dist/tool-launcher.js +5 -4
- package/dist/tool-secret-store.d.ts +170 -0
- package/dist/tool-secret-store.js +834 -0
- package/dist/toolroll-update-ui.js +2 -2
- package/dist/toolroll-update.js +14 -3
- package/dist/tools-ui.d.ts +7 -1
- package/dist/tools-ui.js +19 -10
- package/dist/webhook-limits.d.ts +23 -0
- package/dist/webhook-limits.js +30 -0
- package/dist/webhook-readers.d.ts +56 -0
- package/dist/webhook-readers.js +138 -0
- package/dist/webhook-signing.d.ts +27 -0
- package/dist/webhook-signing.js +119 -0
- package/dist/work-index.d.ts +29 -0
- package/dist/work-index.js +21 -5
- package/dist/workspace-revision.js +3 -1
- package/dist/worktree.d.ts +10 -4
- package/dist/worktree.js +70 -29
- package/package.json +13 -2
- package/scripts/provider-canary.mjs +210 -31
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** The words a "runs on its own" grant signs (flow-unattended.ts), kept free of server imports so the flow page's
|
|
2
|
+
* signing form says each limit exactly as the signature will. */
|
|
3
|
+
export declare const dollarWords: (micro: number) => string;
|
|
4
|
+
/** "Oct 19": the end's day, where space is short (the exact time goes beside it, on hover). */
|
|
5
|
+
export declare const untilDayWords: (iso: string) => string;
|
|
6
|
+
/** "Oct 19, 14:05 UTC": the expiry as every surface says it. */
|
|
7
|
+
export declare const untilWords: (iso: string) => string;
|
|
8
|
+
/** Who approves, with what permissions and against which criteria. */
|
|
9
|
+
export declare function unattendedHeadWords(owner: string, acceptance: {
|
|
10
|
+
task: readonly {
|
|
11
|
+
statement: string;
|
|
12
|
+
}[];
|
|
13
|
+
report: readonly {
|
|
14
|
+
statement: string;
|
|
15
|
+
}[];
|
|
16
|
+
}): string[];
|
|
17
|
+
/** "daily at 09:00" from a stored schedule ("daily:09:00@Europe/London"), kept here so every surface says it alike. */
|
|
18
|
+
export declare function scheduleWords(stored: string): string;
|
|
19
|
+
/** Which schedules the grant covers, by name and time. */
|
|
20
|
+
export declare const unattendedCoverWords: (triggers: readonly {
|
|
21
|
+
words: string;
|
|
22
|
+
}[]) => string;
|
|
23
|
+
/** The optional limits. */
|
|
24
|
+
export declare function unattendedLimitWords(budgetMicrousd: number | null, dailyRunCap: number | null): string[];
|
|
25
|
+
/** What it never covers, and what ends it. */
|
|
26
|
+
export declare const UNATTENDED_RULE_WORDS: readonly string[];
|
|
27
|
+
export declare const unattendedEndWords: (expiry: string) => string;
|
|
28
|
+
export declare const unattendedEndAfterWords: (days: number) => string;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** The words a "runs on its own" grant signs (flow-unattended.ts), kept free of server imports so the flow page's
|
|
2
|
+
* signing form says each limit exactly as the signature will. */
|
|
3
|
+
export const dollarWords = (micro) => `$${(micro / 1_000_000).toFixed(2)}`;
|
|
4
|
+
/** "Oct 19": the end's day, where space is short (the exact time goes beside it, on hover). */
|
|
5
|
+
export const untilDayWords = (iso) => new Intl.DateTimeFormat("en-US", { month: "short", day: "numeric", timeZone: "UTC" }).format(new Date(iso));
|
|
6
|
+
/** "Oct 19, 14:05 UTC": the expiry as every surface says it. */
|
|
7
|
+
export const untilWords = (iso) => `${new Intl.DateTimeFormat("en-US", { month: "short", day: "numeric", timeZone: "UTC" }).format(new Date(iso))}, ${iso.slice(11, 16)} UTC`;
|
|
8
|
+
/** Who approves, with what permissions and against which criteria. */
|
|
9
|
+
export function unattendedHeadWords(owner, acceptance) {
|
|
10
|
+
return [
|
|
11
|
+
`Cards this flow's own schedule adds file their work approved by ${owner}, without waiting in Needs you.`,
|
|
12
|
+
"Builds use safe permissions: routine project commands and edits proceed; risky acts stop for approval.",
|
|
13
|
+
`Builds are checked against: “${acceptance.task.map(one => one.statement).join("”; “")}”.`,
|
|
14
|
+
`Research is checked against: “${acceptance.report.map(one => one.statement).join("”; “")}”.`,
|
|
15
|
+
];
|
|
16
|
+
}
|
|
17
|
+
/** "daily at 09:00" from a stored schedule ("daily:09:00@Europe/London"), kept here so every surface says it alike. */
|
|
18
|
+
export function scheduleWords(stored) {
|
|
19
|
+
const days = ["Sundays", "Mondays", "Tuesdays", "Wednesdays", "Thursdays", "Fridays", "Saturdays"];
|
|
20
|
+
const [when, zone] = stored.split("@");
|
|
21
|
+
const parts = (when ?? "").split(":");
|
|
22
|
+
const tz = zone === undefined ? "" : ` ${zone}`;
|
|
23
|
+
if (parts[0] === "every") {
|
|
24
|
+
const n = Number(parts[1]);
|
|
25
|
+
return n % 1440 === 0 ? `every ${n / 1440} day${n === 1440 ? "" : "s"}` : n % 60 === 0 ? `every ${n / 60} hour${n === 60 ? "" : "s"}` : `every ${n} minutes`;
|
|
26
|
+
}
|
|
27
|
+
if (parts[0] === "daily" || parts[0] === "weekdays")
|
|
28
|
+
return `${parts[0]} at ${parts[1]}:${parts[2]}${tz}`;
|
|
29
|
+
if (parts[0] === "weekly")
|
|
30
|
+
return `${days[Number(parts[1])] ?? "weekly"} at ${parts[2]}:${parts[3]}${tz}`;
|
|
31
|
+
return stored;
|
|
32
|
+
}
|
|
33
|
+
/** Which schedules the grant covers, by name and time. */
|
|
34
|
+
export const unattendedCoverWords = (triggers) => `It covers ${triggers.length === 1 ? "this schedule" : "these schedules"} when ${triggers.length === 1 ? "it fires" : "they fire"} on time: ${triggers.map(one => one.words).join("; ")}. Run now, and schedules added or changed later, wait for you.`;
|
|
35
|
+
/** The optional limits. */
|
|
36
|
+
export function unattendedLimitWords(budgetMicrousd, dailyRunCap) {
|
|
37
|
+
return [
|
|
38
|
+
budgetMicrousd === null ? "No dollar cap per attempt." : `Each attempt may spend up to ${dollarWords(budgetMicrousd)}.`,
|
|
39
|
+
dailyRunCap === null ? "No daily limit on runs." : `At most ${dailyRunCap} run${dailyRunCap === 1 ? "" : "s"} a day (UTC); after that, cards wait for you.`,
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
/** What it never covers, and what ends it. */
|
|
43
|
+
export const UNATTENDED_RULE_WORDS = [
|
|
44
|
+
"Plans are approved only when they keep the filed request exactly. Questions and plan changes still wait for you.",
|
|
45
|
+
"Never covered: Person decides steps, pull request merges, publish or deploy scripts, and anything it sends. Cards people add and other triggers wait as usual.",
|
|
46
|
+
"Editing the flow, its schedules, a script they run or a project file it imports, changing its owner, the owner losing access, or protecting the project ends this.",
|
|
47
|
+
"Signing again replaces it: work it approved that hasn't started goes back to waiting for you.",
|
|
48
|
+
];
|
|
49
|
+
export const unattendedEndWords = (expiry) => `Ends ${untilWords(expiry)}. Revoking it earlier is one click.`;
|
|
50
|
+
export const unattendedEndAfterWords = (days) => `Ends ${days} day${days === 1 ? "" : "s"} after you sign. Revoking it earlier is one click.`;
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import type { AcceptanceCriterion } from "./contracts/scope.js";
|
|
2
|
+
import { untilWords } from "./flow-unattended-words.js";
|
|
3
|
+
import type { FlowRow, FlowTriggerRow, Store } from "./store.js";
|
|
4
|
+
/** Grant history, run reservations and the last prepared script snapshots shared by UI/worker processes. Additive only. */
|
|
5
|
+
export declare const FLOW_UNATTENDED_SCHEMA = "\nCREATE TABLE IF NOT EXISTS flow_script_provenance (\n repo TEXT NOT NULL, name TEXT NOT NULL, snapshot TEXT, PRIMARY KEY (repo, name)\n);\nCREATE TABLE IF NOT EXISTS flow_unattended_grant (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n flow INTEGER NOT NULL,\n repo TEXT NOT NULL,\n flow_revision INTEGER NOT NULL,\n terms_json TEXT NOT NULL,\n digest TEXT NOT NULL,\n signed_by TEXT NOT NULL,\n signed_at TEXT NOT NULL,\n absolute_expiry TEXT NOT NULL,\n revoked_at TEXT,\n revoked_by TEXT,\n revoke_reason TEXT\n);\nCREATE UNIQUE INDEX IF NOT EXISTS flow_unattended_live ON flow_unattended_grant (flow) WHERE revoked_at IS NULL;\nCREATE INDEX IF NOT EXISTS flow_unattended_digest ON flow_unattended_grant (digest);\nCREATE TABLE IF NOT EXISTS flow_unattended_run (\n grant_id INTEGER NOT NULL,\n day TEXT NOT NULL,\n task_id TEXT NOT NULL,\n at TEXT NOT NULL,\n PRIMARY KEY (grant_id, task_id)\n);\nCREATE INDEX IF NOT EXISTS flow_unattended_run_day ON flow_unattended_run (grant_id, day);\n";
|
|
6
|
+
/** The fixed acceptance criteria a flow's work zones file with: the same for every card, so a grant can freeze them. */
|
|
7
|
+
export declare const FLOW_ACCEPTANCE: {
|
|
8
|
+
report: AcceptanceCriterion[];
|
|
9
|
+
task: AcceptanceCriterion[];
|
|
10
|
+
};
|
|
11
|
+
/** The most runs a day a grant may allow. */
|
|
12
|
+
export declare const UNATTENDED_MAX_RUNS = 50;
|
|
13
|
+
/** The largest per-attempt budget a grant may name: $100. */
|
|
14
|
+
export declare const UNATTENDED_MAX_BUDGET_MICROUSD = 100000000;
|
|
15
|
+
/** The code a script schedule runs, as signed: the script's version and content digest, and for one that runs a project
|
|
16
|
+
* file, that file's path and, sorted by path, the digest of its bytes and of every project file it statically imports. */
|
|
17
|
+
export type SignedScript = {
|
|
18
|
+
provenance: 2;
|
|
19
|
+
name: string;
|
|
20
|
+
version: number;
|
|
21
|
+
digest: string;
|
|
22
|
+
file: string | null;
|
|
23
|
+
files: {
|
|
24
|
+
path: string;
|
|
25
|
+
digest: string;
|
|
26
|
+
}[];
|
|
27
|
+
};
|
|
28
|
+
/** One schedule a grant covers: which trigger, what sort, the digest of its settings when signed, and its name in words.
|
|
29
|
+
* `script` is there exactly when the kind is "script". */
|
|
30
|
+
export type CoveredTrigger = {
|
|
31
|
+
id: number;
|
|
32
|
+
kind: "schedule" | "script" | "plane-review";
|
|
33
|
+
digest: string;
|
|
34
|
+
words: string;
|
|
35
|
+
script?: SignedScript;
|
|
36
|
+
};
|
|
37
|
+
export type UnattendedTerms = {
|
|
38
|
+
flow: number;
|
|
39
|
+
/** Saving the flow moves its revision: what was signed was this drawing. */
|
|
40
|
+
flowRevision: number;
|
|
41
|
+
repo: string;
|
|
42
|
+
/** The signer, who must stay the flow's owner. */
|
|
43
|
+
owner: string;
|
|
44
|
+
/** The schedules signed for, frozen: any other trigger, or one of these changed, is not covered. */
|
|
45
|
+
triggers: CoveredTrigger[];
|
|
46
|
+
/** Always safe: an escalated posture is never covered. */
|
|
47
|
+
permissions: "safe";
|
|
48
|
+
acceptance: {
|
|
49
|
+
report: AcceptanceCriterion[];
|
|
50
|
+
task: AcceptanceCriterion[];
|
|
51
|
+
};
|
|
52
|
+
perAttemptBudgetMicrousd: number | null;
|
|
53
|
+
/** Filings per UTC day, reserved at filing. */
|
|
54
|
+
dailyRunCap: number | null;
|
|
55
|
+
absoluteExpiry: string;
|
|
56
|
+
};
|
|
57
|
+
export declare const unattendedTermsJson: (terms: UnattendedTerms) => string;
|
|
58
|
+
/** sha256 over a domain-separated canonical encoding, 32 hex like the mode digest. */
|
|
59
|
+
export declare function unattendedDigestOf(terms: UnattendedTerms): string;
|
|
60
|
+
/** Strict rehydration: anything unexpected is null, never a guess. */
|
|
61
|
+
export declare function unattendedTermsFromJson(json: string | null): UnattendedTerms | null;
|
|
62
|
+
export { untilWords };
|
|
63
|
+
/** Every term in words: what the ceremony shows and the password signs. */
|
|
64
|
+
export declare function unattendedWords(terms: UnattendedTerms): string[];
|
|
65
|
+
export type UnattendedGrant = {
|
|
66
|
+
id: number;
|
|
67
|
+
flow: number;
|
|
68
|
+
repo: string;
|
|
69
|
+
terms: UnattendedTerms;
|
|
70
|
+
digest: string;
|
|
71
|
+
signedBy: string;
|
|
72
|
+
signedAt: string;
|
|
73
|
+
absoluteExpiry: string;
|
|
74
|
+
};
|
|
75
|
+
/** SQL: whether the grant whose digest is `digest` still stands at `now` for work in `repo` — live, unexpired, its
|
|
76
|
+
* signer an active approver who can still reach the flow's project and this one, still the owner of the very flow
|
|
77
|
+
* revision signed, and neither project protected. Shared by every dispatch belt. */
|
|
78
|
+
export declare const grantStandsSql: (digest: string, now: string, repo: string) => string;
|
|
79
|
+
/** Why a grant ended, as its row and ledger line say it. A renewal's ledger line is the new signature's. */
|
|
80
|
+
export type UnattendedEnd = "expired" | "revoked" | "renewed" | "schedule changed" | "script changed" | "project protected" | "access changed";
|
|
81
|
+
/**
|
|
82
|
+
* The one road for what ends grants from outside this module (store.ts calls it): a flow's schedule added, paused,
|
|
83
|
+
* resumed or removed; a project's approval rules protecting work; an account's access or standing changing. Every live
|
|
84
|
+
* grant the filter names ends now, durably, with its ledger line, and its queued approvals are withdrawn. Call inside
|
|
85
|
+
* the mutation's transaction. Returns how many ended.
|
|
86
|
+
*/
|
|
87
|
+
export declare function endUnattendedGrants(store: Store, filter: {
|
|
88
|
+
flow: number;
|
|
89
|
+
} | {
|
|
90
|
+
repo: string;
|
|
91
|
+
} | {
|
|
92
|
+
signer: string;
|
|
93
|
+
} | {
|
|
94
|
+
script: {
|
|
95
|
+
repo: string;
|
|
96
|
+
name: string;
|
|
97
|
+
};
|
|
98
|
+
}, by: string, reason: Exclude<UnattendedEnd, "expired" | "revoked" | "renewed">, now: Date): number;
|
|
99
|
+
/** The live grant for a flow, or null. One past its expiry is closed here, durably (like activeMode). A grant whose
|
|
100
|
+
* signer is no longer an active approver, or whose flow moved on, covers nothing. */
|
|
101
|
+
export declare function activeUnattendedGrant(store: Store, flowId: number, now: Date): UnattendedGrant | null;
|
|
102
|
+
/** sha256 over a trigger's identity and canonical settings: what a grant freezes for each schedule it covers. */
|
|
103
|
+
export declare function triggerDigestOf(trigger: Pick<FlowTriggerRow, "id" | "flow" | "kind" | "configJson">): string | null;
|
|
104
|
+
/** Asynchronous preparation, never called from filing transactions or page rendering. */
|
|
105
|
+
export declare function scriptProvenanceOf(store: Store, repo: string, name: string, fresh?: boolean): Promise<SignedScript | null>;
|
|
106
|
+
export declare function prepareUnattendedCandidates(store: Store, flowId: number): Promise<void>;
|
|
107
|
+
/** What an on-time script firing ran, as its firing records it: a digest of the code pinned just before and just after
|
|
108
|
+
* the run, when both were the same and were the script row that ran; else null (it can't have run the code signed). */
|
|
109
|
+
export declare function scriptRanDigestOf(before: SignedScript | null, after: SignedScript | null, ran: {
|
|
110
|
+
version: number;
|
|
111
|
+
digest: string;
|
|
112
|
+
}): string | null;
|
|
113
|
+
/** Whether `flowId`'s live grant signed `triggerId`'s script: only then does a firing pin the code it runs. */
|
|
114
|
+
export declare function grantSignsScriptOf(store: Store, flowId: number, triggerId: number, now: Date): boolean;
|
|
115
|
+
/** A schedule a grant could cover, and whether it is covered only when the owner picks it (`optional`, with why). */
|
|
116
|
+
export type UnattendedCandidate = CoveredTrigger & {
|
|
117
|
+
optional: string | null;
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* The flow's active schedules a grant could cover. A plain schedule makes its own card from its own words, so it is
|
|
121
|
+
* covered by default. A script's items and a plane review's problems are outside content (issues, mail, what a run
|
|
122
|
+
* saw), so they are covered only when the owner picks them. A standing order files under its own signed terms, and a
|
|
123
|
+
* paused or unreadable schedule, or a script whose code can't be read safely, is never offered.
|
|
124
|
+
*/
|
|
125
|
+
export declare function unattendedCandidates(store: Store, flowId: number): UnattendedCandidate[];
|
|
126
|
+
/** A digest of the schedules the page offered, so a signature never covers one the person didn't read. */
|
|
127
|
+
export declare const candidatesDigestOf: (candidates: readonly UnattendedCandidate[]) => string;
|
|
128
|
+
/** Why `signer` can't let this flow run on its own, or null: what the flow page shows instead of the form. */
|
|
129
|
+
export declare function unattendedSignProblem(store: Store, flow: FlowRow, signer: string): string | null;
|
|
130
|
+
/** `include`: the schedules (trigger ids) the owner picked beyond the plain ones covered by default. */
|
|
131
|
+
export type UnattendedAsk = {
|
|
132
|
+
days: number;
|
|
133
|
+
budgetMicrousd: number | null;
|
|
134
|
+
dailyRunCap: number | null;
|
|
135
|
+
include?: number[];
|
|
136
|
+
};
|
|
137
|
+
/** Read what a person typed: whole days 1–MODE_MAX_DAYS, an optional dollar budget, an optional runs-a-day cap. */
|
|
138
|
+
export declare function parseUnattendedAsk(input: {
|
|
139
|
+
days: unknown;
|
|
140
|
+
budget?: unknown;
|
|
141
|
+
runs?: unknown;
|
|
142
|
+
include?: unknown;
|
|
143
|
+
}): {
|
|
144
|
+
ok: true;
|
|
145
|
+
ask: UnattendedAsk;
|
|
146
|
+
} | {
|
|
147
|
+
ok: false;
|
|
148
|
+
message: string;
|
|
149
|
+
};
|
|
150
|
+
/** The exact terms a signature would cover now, for these schedules. */
|
|
151
|
+
export declare function unattendedTermsFor(flow: FlowRow, owner: string, ask: UnattendedAsk, triggers: readonly CoveredTrigger[], now: Date): UnattendedTerms;
|
|
152
|
+
/** Sign (or renew) the grant. The caller has already checked the signer's password; every predicate is proved again
|
|
153
|
+
* here against the flow as it now stands: files asynchronously first, then database facts inside the transaction. `sawRevision` and `sawSchedules` (candidatesDigestOf),
|
|
154
|
+
* when given, are the flow and the schedules the person read. Renewing ends the old grant and withdraws what it sealed. */
|
|
155
|
+
export declare function signUnattended(store: Store, input: {
|
|
156
|
+
flow: number;
|
|
157
|
+
signer: string;
|
|
158
|
+
ask: UnattendedAsk;
|
|
159
|
+
sawRevision?: number;
|
|
160
|
+
sawSchedules?: string;
|
|
161
|
+
}, now: Date): Promise<{
|
|
162
|
+
ok: true;
|
|
163
|
+
grant: UnattendedGrant;
|
|
164
|
+
} | {
|
|
165
|
+
ok: false;
|
|
166
|
+
message: string;
|
|
167
|
+
}>;
|
|
168
|
+
/** One click for any approver on the project: lowering authority needs no password. False when there was none. */
|
|
169
|
+
export declare function revokeUnattended(store: Store, flowId: number, by: string, now: Date): boolean;
|
|
170
|
+
/**
|
|
171
|
+
* Whether a card came from one of the schedules this grant signed for, fired on time after it was signed: the firing
|
|
172
|
+
* names the card and was the clock's (never Run now), its trigger is still active with the very settings signed, and no
|
|
173
|
+
* person has moved the card or sent it back since. Anything else is a person's card, or one the grant never read.
|
|
174
|
+
* A script schedule's firing must have run the very code signed (scriptRanDigestOf), and it must still be that code;
|
|
175
|
+
* when it isn't, the grant ends here (unattendedCoverageFor).
|
|
176
|
+
*/
|
|
177
|
+
export declare function cardFromSignedSchedule(store: Store, grant: UnattendedGrant, cardId: number, requireScript?: boolean): boolean;
|
|
178
|
+
/** How many runs a grant has filed on `now`'s UTC day. */
|
|
179
|
+
export declare function unattendedRunsToday(store: Store, grantId: number, now: Date): number;
|
|
180
|
+
/** Whether the grant covers this card's next filing (in `repo`) now; call inside the filing transaction. */
|
|
181
|
+
export declare function unattendedCoverageFor(store: Store, flow: FlowRow, card: {
|
|
182
|
+
id: number;
|
|
183
|
+
}, repo: string, now: Date): UnattendedGrant | null;
|
|
184
|
+
/** Count one run against the grant's day, in one statement that admits it only under the cap (so two filings racing
|
|
185
|
+
* on two connections can't both take the last run). False when the day is full; then nothing is sealed. */
|
|
186
|
+
export declare function reserveUnattendedRun(store: Store, grant: UnattendedGrant, taskId: string, now: Date): boolean;
|
|
187
|
+
/** Give back a run reserved for a filing that then couldn't be sealed. */
|
|
188
|
+
export declare function releaseUnattendedRun(store: Store, grant: UnattendedGrant, taskId: string): void;
|
|
189
|
+
/** The grant that sealed (or pre-authorized) a task still stands for it: the same live digest, the flow unchanged and
|
|
190
|
+
* still owned by the signer, the signer able to approve in the task's project, its scripts' code unchanged (else it
|
|
191
|
+
* ends here), and the work not protected. */
|
|
192
|
+
export declare function unattendedGrantStands(store: Store, digest: string, signer: string, taskRepo: string | null, touches: readonly string[], now: Date): boolean;
|
|
193
|
+
/** The flow page's and CLI's view of the grant: the live state, and whether (and why not) this viewer can sign. */
|
|
194
|
+
export type UnattendedView = {
|
|
195
|
+
active: {
|
|
196
|
+
until: string;
|
|
197
|
+
untilWords: string;
|
|
198
|
+
signedBy: string;
|
|
199
|
+
budgetMicrousd: number | null;
|
|
200
|
+
dailyRunCap: number | null;
|
|
201
|
+
runsToday: number;
|
|
202
|
+
words: string[];
|
|
203
|
+
covers: string[];
|
|
204
|
+
} | null;
|
|
205
|
+
canSign: boolean;
|
|
206
|
+
problem: string | null;
|
|
207
|
+
maxDays: number;
|
|
208
|
+
/** Whether the flow has a schedule, the only thing a grant covers. */
|
|
209
|
+
scheduled: boolean;
|
|
210
|
+
/** What a signature covers besides the limits and schedules the form chooses (unattendedLimitWords, unattendedCoverWords,
|
|
211
|
+
* unattendedEndAfterWords). */
|
|
212
|
+
terms: {
|
|
213
|
+
head: string[];
|
|
214
|
+
rules: string[];
|
|
215
|
+
};
|
|
216
|
+
/** The schedules it could cover (optional ones only when picked), and their digest, which the form sends back. */
|
|
217
|
+
schedules: {
|
|
218
|
+
id: number;
|
|
219
|
+
words: string;
|
|
220
|
+
optional: string | null;
|
|
221
|
+
}[];
|
|
222
|
+
schedulesDigest: string;
|
|
223
|
+
};
|
|
224
|
+
export declare function unattendedViewOf(store: Store, flow: FlowRow, viewer: {
|
|
225
|
+
name: string;
|
|
226
|
+
approver: boolean;
|
|
227
|
+
}, now: Date): UnattendedView;
|