@quantiya/codevibe-core 2.0.0 → 2.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.
- package/dist/__tests__/cp-5-baseline-invariants.test.d.ts +1 -0
- package/dist/adapter/__tests__/capabilities.test.d.ts +1 -0
- package/dist/adapter/__tests__/contract-conformance.test.d.ts +1 -0
- package/dist/adapter/__tests__/packets.test.d.ts +1 -0
- package/dist/adapter/__tests__/progress.test.d.ts +1 -0
- package/dist/adapter/__tests__/registry.test.d.ts +1 -0
- package/dist/adapter/__tests__/smoke/claude.smoke.test.d.ts +1 -0
- package/dist/adapter/__tests__/smoke/codex.smoke.test.d.ts +1 -0
- package/dist/adapter/__tests__/smoke/gemini.smoke.test.d.ts +1 -0
- package/dist/adapter/capabilities.d.ts +68 -0
- package/dist/adapter/index.d.ts +7 -0
- package/dist/adapter/packets.d.ts +129 -0
- package/dist/adapter/progress.d.ts +93 -0
- package/dist/adapter/registry.d.ts +24 -0
- package/dist/adapter/types.d.ts +22 -0
- package/dist/appsync/__tests__/appsync-client-apply-user-decision.test.d.ts +1 -0
- package/dist/appsync/__tests__/appsync-client-classb.test.d.ts +1 -0
- package/dist/appsync/__tests__/appsync-client-planner.test.d.ts +1 -0
- package/dist/appsync/__tests__/appsync-client.test.d.ts +1 -0
- package/dist/appsync/appsync-client.d.ts +412 -0
- package/dist/appsync/index.d.ts +1 -1
- package/dist/appsync/queries.d.ts +15 -0
- package/dist/auth/__tests__/auth-telemetry.test.d.ts +1 -0
- package/dist/auth/auth-telemetry.d.ts +98 -5
- package/dist/companion-mode/__tests__/persist-preference.test.d.ts +1 -0
- package/dist/companion-mode/__tests__/resolve-agent.test.d.ts +1 -0
- package/dist/companion-mode/agent-picker.d.ts +9 -0
- package/dist/companion-mode/index.d.ts +55 -0
- package/dist/companion-mode/persist-preference.d.ts +24 -0
- package/dist/companion-mode/resolve-agent.d.ts +41 -0
- package/dist/index.d.ts +11 -3
- package/dist/index.js +243 -42
- package/dist/keychain/keychain-manager.d.ts +16 -2
- package/dist/local-executor/__tests__/authority-symlink-fixture.d.ts +15 -0
- package/dist/local-executor/__tests__/authority.test.d.ts +1 -0
- package/dist/local-executor/__tests__/class-a-emit.test.d.ts +1 -0
- package/dist/local-executor/__tests__/class-b-consumer.integration.test.d.ts +1 -0
- package/dist/local-executor/__tests__/class-b-consumer.test.d.ts +1 -0
- package/dist/local-executor/__tests__/hook-bridge.test.d.ts +1 -0
- package/dist/local-executor/__tests__/local-executor.integration.test.d.ts +1 -0
- package/dist/local-executor/__tests__/spawn.test.d.ts +1 -0
- package/dist/local-executor/__tests__/verification-runner.test.d.ts +1 -0
- package/dist/local-executor/authority.d.ts +29 -0
- package/dist/local-executor/class-a-emit.d.ts +138 -0
- package/dist/local-executor/class-b-consumer.d.ts +121 -0
- package/dist/local-executor/hook-bridge.d.ts +36 -0
- package/dist/local-executor/index.d.ts +8 -0
- package/dist/local-executor/local-executor-impl.d.ts +83 -0
- package/dist/local-executor/spawn.d.ts +6 -0
- package/dist/local-executor/types.d.ts +183 -0
- package/dist/local-executor/verification-gates/build.d.ts +6 -0
- package/dist/local-executor/verification-gates/deploy-preflight.d.ts +6 -0
- package/dist/local-executor/verification-gates/diff-sanity.d.ts +6 -0
- package/dist/local-executor/verification-gates/hostile-grep.d.ts +6 -0
- package/dist/local-executor/verification-gates/lint.d.ts +6 -0
- package/dist/local-executor/verification-gates/shell-runner.d.ts +40 -0
- package/dist/local-executor/verification-gates/source-traceability.d.ts +6 -0
- package/dist/local-executor/verification-gates/tests.d.ts +6 -0
- package/dist/local-executor/verification-gates/typecheck.d.ts +6 -0
- package/dist/local-executor/verification-runner.d.ts +28 -0
- package/dist/orchestration/__tests__/setup-bootstrap.test.d.ts +1 -0
- package/dist/orchestration/__tests__/setup-failure-recourse.test.d.ts +1 -0
- package/dist/orchestration/__tests__/setup-save.test.d.ts +1 -0
- package/dist/orchestration/__tests__/setup-seat-picker.test.d.ts +1 -0
- package/dist/orchestration/__tests__/setup-telemetry.test.d.ts +1 -0
- package/dist/orchestration/__tests__/setup-test-agents.test.d.ts +1 -0
- package/dist/orchestration/__tests__/setup-types.test.d.ts +1 -0
- package/dist/orchestration/__tests__/setup-wizard.test.d.ts +1 -0
- package/dist/orchestration/__tests__/v1-options.test.d.ts +1 -0
- package/dist/orchestration/detect-agents.d.ts +2 -1
- package/dist/orchestration/index.d.ts +1 -0
- package/dist/orchestration/orchestration-cli.d.ts +4 -1
- package/dist/orchestration/setup-bootstrap.d.ts +146 -0
- package/dist/orchestration/setup-failure-recourse.d.ts +23 -0
- package/dist/orchestration/setup-save.d.ts +47 -0
- package/dist/orchestration/setup-seat-picker.d.ts +72 -0
- package/dist/orchestration/setup-telemetry.d.ts +54 -0
- package/dist/orchestration/setup-test-agents.d.ts +108 -0
- package/dist/orchestration/setup-types.d.ts +140 -0
- package/dist/orchestration/setup-wizard.d.ts +57 -0
- package/dist/orchestration/v1-options.d.ts +97 -0
- package/dist/orchestration-shell/__tests__/cli-authority-bridge.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cli-planner-stack.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cli-singleton-enforcement.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cli-stub-session-adapter.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/components.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/emit-shell-event.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/gate-prompts.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/hostile-grep.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/mode-selection.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/process-markers.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/reducer.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/runOrchestrationShell-classify-dispatch.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/runOrchestrationShell-planner-wiring.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/runOrchestrationShell-signal.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/runOrchestrationShell.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/slash-router.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/sticky-preference.test.d.ts +1 -0
- package/dist/orchestration-shell/cli.d.ts +96 -0
- package/dist/orchestration-shell/cli.js +8309 -0
- package/dist/orchestration-shell/cohort-flag.d.ts +16 -0
- package/dist/orchestration-shell/components/CodeVibeLogo.d.ts +2 -0
- package/dist/orchestration-shell/components/ConversationPane.d.ts +7 -0
- package/dist/orchestration-shell/components/GatePromptEntry.d.ts +9 -0
- package/dist/orchestration-shell/components/InputBar.d.ts +41 -0
- package/dist/orchestration-shell/components/OrchestrationApp.d.ts +63 -0
- package/dist/orchestration-shell/components/StatusBar.d.ts +7 -0
- package/dist/orchestration-shell/components/nodes/AdvisoryEntry.d.ts +8 -0
- package/dist/orchestration-shell/components/nodes/GateStatusNode.d.ts +8 -0
- package/dist/orchestration-shell/components/nodes/PlannerDecisionEntry.d.ts +8 -0
- package/dist/orchestration-shell/components/nodes/ReviewerQuorumStatusNode.d.ts +8 -0
- package/dist/orchestration-shell/components/nodes/SlashOutputEntry.d.ts +8 -0
- package/dist/orchestration-shell/components/nodes/SubagentEventEntry.d.ts +8 -0
- package/dist/orchestration-shell/components/nodes/UserMessageEntry.d.ts +8 -0
- package/dist/orchestration-shell/emit-shell-event.d.ts +64 -0
- package/dist/orchestration-shell/gate-prompts.d.ts +123 -0
- package/dist/orchestration-shell/index.d.ts +100 -0
- package/dist/orchestration-shell/ink-runtime.d.ts +64 -0
- package/dist/orchestration-shell/mode-selection.d.ts +46 -0
- package/dist/orchestration-shell/non-tty-fallback.d.ts +46 -0
- package/dist/orchestration-shell/process-markers.d.ts +12 -0
- package/dist/orchestration-shell/reducer.d.ts +8 -0
- package/dist/orchestration-shell/slash-router.d.ts +45 -0
- package/dist/orchestration-shell/sticky-preference.d.ts +24 -0
- package/dist/orchestration-shell/store.d.ts +17 -0
- package/dist/orchestration-shell/types.d.ts +417 -0
- package/dist/planner/__tests__/cache-clarification-bypass.test.d.ts +1 -0
- package/dist/planner/__tests__/cache.test.d.ts +1 -0
- package/dist/planner/__tests__/client.test.d.ts +1 -0
- package/dist/planner/__tests__/health-machine-transitions.test.d.ts +1 -0
- package/dist/planner/__tests__/types-zod.test.d.ts +1 -0
- package/dist/planner/adapter.d.ts +16 -0
- package/dist/planner/cache.d.ts +35 -0
- package/dist/planner/client.d.ts +103 -0
- package/dist/planner/health-state.d.ts +24 -0
- package/dist/planner/index.d.ts +5 -0
- package/dist/planner/types.d.ts +113 -0
- package/dist/session/__tests__/session-resume-service-keys.test.d.ts +1 -0
- package/dist/session/session-rekey.d.ts +40 -0
- package/dist/session/session-resume.d.ts +25 -0
- package/dist/structural-summary/__tests__/__fixtures__/fixture-helpers.d.ts +11 -0
- package/dist/structural-summary/__tests__/assembler.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/generator.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/language-detect.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/manifest-parsers/cargo.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/manifest-parsers/gomod.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/manifest-parsers/gradle.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/manifest-parsers/index.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/manifest-parsers/npm.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/manifest-parsers/podfile.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/manifest-parsers/pyproject.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/opt-in-store.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/privacy-filter.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/safe-file-read.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/user-ignore-matcher.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/walker.test.d.ts +1 -0
- package/dist/structural-summary/generator.d.ts +8 -0
- package/dist/structural-summary/index.d.ts +7 -0
- package/dist/structural-summary/manifest-parsers/cargo.d.ts +3 -0
- package/dist/structural-summary/manifest-parsers/index.d.ts +7 -0
- package/dist/structural-summary/manifest-parsers/npm.d.ts +3 -0
- package/dist/structural-summary/manifest-parsers/other.d.ts +17 -0
- package/dist/structural-summary/opt-in-store.d.ts +24 -0
- package/dist/structural-summary/privacy-filter.d.ts +110 -0
- package/dist/structural-summary/safe-file-read.d.ts +11 -0
- package/dist/structural-summary/types.d.ts +215 -0
- package/dist/structural-summary/user-ignore-matcher.d.ts +9 -0
- package/dist/structural-summary/walker.d.ts +20 -0
- package/dist/types/events.d.ts +17 -2
- package/package.json +17 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CreateEventInput, CreateSessionInput, UpdateSessionInput, UpdateEventStatusInput, Event, Session, EventSource, DeviceKey, GrantSessionKeyInput, UpdateReviewerPolicyInput, UserReviewerPolicySnapshot } from '../types';
|
|
2
|
+
import type { PostDecisionAction } from '../orchestration-shell/types';
|
|
2
3
|
/**
|
|
3
4
|
* Download URL response
|
|
4
5
|
*/
|
|
@@ -6,6 +7,47 @@ export interface DownloadUrlResponse {
|
|
|
6
7
|
downloadUrl: string;
|
|
7
8
|
expiresAt: string;
|
|
8
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* CP-1.b IMPL r2 M-4 — Typed GraphQL error that preserves AppSync's
|
|
12
|
+
* `errorType` and `extensions` fields, alongside the human-readable
|
|
13
|
+
* `message`. Stage 2 r1's `graphqlRequest()` threw a plain
|
|
14
|
+
* `Error("GraphQL error: <message>")` and silently dropped
|
|
15
|
+
* `errorType`, which broke `BackendPlannerClient.classifyTransportError`
|
|
16
|
+
* (it discriminates on `err.errorType` to separate
|
|
17
|
+
* `BudgetExceeded` / `TierGateRejected` from provider-health failures).
|
|
18
|
+
*
|
|
19
|
+
* Callers may catch this class to inspect `errorType` directly. Code
|
|
20
|
+
* paths that still parse error.message will continue to work because
|
|
21
|
+
* the message is unchanged ("GraphQL error: <message>").
|
|
22
|
+
*/
|
|
23
|
+
export declare class AppSyncGraphQLError extends Error {
|
|
24
|
+
readonly errorType?: string;
|
|
25
|
+
readonly extensions?: unknown;
|
|
26
|
+
readonly path?: unknown;
|
|
27
|
+
constructor(opts: {
|
|
28
|
+
message: string;
|
|
29
|
+
errorType?: string;
|
|
30
|
+
extensions?: unknown;
|
|
31
|
+
path?: unknown;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Discriminator for the most recent `authenticateWithStoredTokens()`
|
|
36
|
+
* failure. Lets callers distinguish a genuine "no tokens / refresh
|
|
37
|
+
* rejected" outcome from a transient network failure during the
|
|
38
|
+
* Cognito refresh-token POST.
|
|
39
|
+
*
|
|
40
|
+
* Stage 2 round-1 Codex M1: the production refresh path returns
|
|
41
|
+
* `false` on every error (including network blow-ups inside
|
|
42
|
+
* `callCognitoRefresh`'s catch block), so the wizard's auth-vs-network
|
|
43
|
+
* heuristic — which only ran on caught throws — never fired in
|
|
44
|
+
* production. Recording the kind on every false-return path lets
|
|
45
|
+
* `setup-bootstrap.ts:defaultClientFactory()` route network-shaped
|
|
46
|
+
* refresh failures to `subscription_status_network` (per §6 row
|
|
47
|
+
* "transient 5xx during refresh") instead of misleading the user with
|
|
48
|
+
* a "not signed in" abort.
|
|
49
|
+
*/
|
|
50
|
+
export type AuthFailureKind = 'no_tokens' | 'refresh_auth_rejected' | 'refresh_network';
|
|
9
51
|
/**
|
|
10
52
|
* AppSync GraphQL client with WebSocket subscriptions
|
|
11
53
|
*/
|
|
@@ -15,7 +57,29 @@ export declare class AppSyncClient {
|
|
|
15
57
|
private currentEmail;
|
|
16
58
|
private tokens;
|
|
17
59
|
private activeSubscriptions;
|
|
60
|
+
/**
|
|
61
|
+
* Set by `authenticateWithStoredTokens()` on every false-return path
|
|
62
|
+
* (and reset to `null` on success). Read by callers (e.g., the
|
|
63
|
+
* wizard's `defaultClientFactory`) to discriminate auth-rejection
|
|
64
|
+
* vs network-failure without re-running the auth call. Stage 2
|
|
65
|
+
* round-1 Codex M1.
|
|
66
|
+
*/
|
|
67
|
+
private lastAuthFailureKind;
|
|
68
|
+
/**
|
|
69
|
+
* Sentinel set inside `performRefresh` / `callCognitoRefresh` when
|
|
70
|
+
* the refresh round-trip fails with a network-shaped error (DNS,
|
|
71
|
+
* socket reset, fetch failed, 5xx). Reset to `false` at the start
|
|
72
|
+
* of each `performRefresh`. Read by `authenticateWithStoredTokens`
|
|
73
|
+
* to classify a `refreshTokens()=false` return as
|
|
74
|
+
* `refresh_network` vs `refresh_auth_rejected`. Internal — never
|
|
75
|
+
* exposed.
|
|
76
|
+
*/
|
|
77
|
+
private lastRefreshNetworkError;
|
|
78
|
+
private pendingRefresh;
|
|
79
|
+
private lastRefreshFailureAt;
|
|
80
|
+
private static readonly REFRESH_BACKOFF_MS;
|
|
18
81
|
private deviceKeyWatcher;
|
|
82
|
+
private sessionUpdateWatchers;
|
|
19
83
|
private environment;
|
|
20
84
|
constructor();
|
|
21
85
|
/**
|
|
@@ -26,6 +90,30 @@ export declare class AppSyncClient {
|
|
|
26
90
|
* Get the current authenticated user email
|
|
27
91
|
*/
|
|
28
92
|
getCurrentUserEmail(): string | null;
|
|
93
|
+
/**
|
|
94
|
+
* Returns the kind of the most recent
|
|
95
|
+
* `authenticateWithStoredTokens()` failure, or `null` if the call
|
|
96
|
+
* succeeded (or has never been called).
|
|
97
|
+
*
|
|
98
|
+
* Stage 2 round-1 Codex M1. Callers (today: `setup-bootstrap.ts
|
|
99
|
+
* :defaultClientFactory`) use this to distinguish network blow-ups
|
|
100
|
+
* during the Cognito refresh-token POST from genuine auth
|
|
101
|
+
* rejections. The wizard maps `'refresh_network'` to
|
|
102
|
+
* `subscription_status_network` (don't tell a signed-in user to
|
|
103
|
+
* re-login when their tokens are valid and the network is broken)
|
|
104
|
+
* and the other two kinds to `not_signed_in` (preserves
|
|
105
|
+
* pre-Codex-M1 behavior).
|
|
106
|
+
*/
|
|
107
|
+
getLastAuthFailureKind(): AuthFailureKind | null;
|
|
108
|
+
/**
|
|
109
|
+
* Heuristic — does the error message look like a transient network
|
|
110
|
+
* failure rather than an auth-token rejection? Mirrors
|
|
111
|
+
* `setup-bootstrap.ts:isNetworkLikeError` byte-for-byte so the same
|
|
112
|
+
* classifier runs both inside the client (for refresh-path
|
|
113
|
+
* discrimination) and at the bootstrap boundary (for caught-throw
|
|
114
|
+
* routing). Stage 2 round-1 Codex M1.
|
|
115
|
+
*/
|
|
116
|
+
private static isNetworkLikeMessage;
|
|
29
117
|
/**
|
|
30
118
|
* Authenticate using stored OAuth tokens from keychain
|
|
31
119
|
*/
|
|
@@ -34,6 +122,47 @@ export declare class AppSyncClient {
|
|
|
34
122
|
* Refresh expired tokens
|
|
35
123
|
*/
|
|
36
124
|
private refreshTokens;
|
|
125
|
+
/**
|
|
126
|
+
* Do the work of refreshing tokens. Tries the caller-supplied tokens
|
|
127
|
+
* first; on failure, re-reads from storage and retries once with a
|
|
128
|
+
* potentially-fresher refresh token. This is the self-healing path
|
|
129
|
+
* that lets `codevibe login` (which writes new tokens to the
|
|
130
|
+
* keychain) recover running daemons without requiring a restart:
|
|
131
|
+
* the in-memory copy the daemon cached at boot may be invalid, but
|
|
132
|
+
* whatever the user just wrote from the login flow is still valid.
|
|
133
|
+
*
|
|
134
|
+
* Splitting the two attempts into a pure-network helper keeps the
|
|
135
|
+
* orchestration readable without duplicating the fetch + body-shape
|
|
136
|
+
* plumbing.
|
|
137
|
+
*/
|
|
138
|
+
private performRefresh;
|
|
139
|
+
/**
|
|
140
|
+
* POST to Cognito's /oauth2/token with a refresh_token grant.
|
|
141
|
+
* Returns the parsed body on 200, or null on any failure (network
|
|
142
|
+
* error, non-2xx response, JSON parse failure). Caller decides how
|
|
143
|
+
* to proceed — this helper is side-effect-free beyond logging.
|
|
144
|
+
*/
|
|
145
|
+
private callCognitoRefresh;
|
|
146
|
+
/**
|
|
147
|
+
* Apply a successful refresh response: update in-memory cache first,
|
|
148
|
+
* clear the backoff sentinel, then persist to storage. Success here
|
|
149
|
+
* is defined as "the process has usable fresh tokens in memory" —
|
|
150
|
+
* storage persistence is degraded-success, not a failure mode.
|
|
151
|
+
*
|
|
152
|
+
* Ordering matters. The API call to Cognito already succeeded, which
|
|
153
|
+
* means we hold valid access/id tokens right now. If we delayed the
|
|
154
|
+
* in-memory update until after persistence and the keychain write
|
|
155
|
+
* threw (keychain locked, disk full, file-backend permission error),
|
|
156
|
+
* we'd be stuck with stale-and-known-dead tokens in memory while
|
|
157
|
+
* holding valid fresh tokens in local scope that vanish at the end
|
|
158
|
+
* of this function. That would re-break both guarantees this hotfix
|
|
159
|
+
* makes: no-restart recovery becomes "restart required to escape
|
|
160
|
+
* the keychain-lock window," and backoff stays unarmed so the
|
|
161
|
+
* caller hot-loops against a working Cognito endpoint — R1's MEDIUM
|
|
162
|
+
* on round 1 of this review. Persistence-failure is loud-logged
|
|
163
|
+
* so operators can see degraded durability without losing availability.
|
|
164
|
+
*/
|
|
165
|
+
private applyRefreshedTokens;
|
|
37
166
|
/**
|
|
38
167
|
* Check if authenticated
|
|
39
168
|
*/
|
|
@@ -70,10 +199,69 @@ export declare class AppSyncClient {
|
|
|
70
199
|
* List events for a session
|
|
71
200
|
*/
|
|
72
201
|
listEvents(sessionId: string, source?: EventSource, limit?: number): Promise<Event[]>;
|
|
202
|
+
/**
|
|
203
|
+
* List the authenticated user's sessions. Paginates automatically
|
|
204
|
+
* via nextToken so callers always get the complete set.
|
|
205
|
+
*/
|
|
206
|
+
listSessions(limit?: number): Promise<Array<{
|
|
207
|
+
sessionId: string;
|
|
208
|
+
agentType: string;
|
|
209
|
+
status: string;
|
|
210
|
+
lastHeartbeatAt: string | null;
|
|
211
|
+
}>>;
|
|
212
|
+
/**
|
|
213
|
+
* Mark stale ACTIVE sessions of a given agentType INACTIVE so they
|
|
214
|
+
* stop appearing in the mobile app's session list. Called at daemon
|
|
215
|
+
* startup to clean up after daemons that died without running their
|
|
216
|
+
* graceful shutdown (crash, auth-loop death, force-kill, power loss).
|
|
217
|
+
*
|
|
218
|
+
* Staleness rule: lastHeartbeatAt is older than `staleThresholdMs`
|
|
219
|
+
* (default 15 min — a conservative ~7.5× the 2-min heartbeat
|
|
220
|
+
* interval, giving legitimately-active daemons on other machines
|
|
221
|
+
* ample margin before we consider their session abandoned).
|
|
222
|
+
*
|
|
223
|
+
* Safety:
|
|
224
|
+
* - Only sessions with status === 'ACTIVE' are candidates.
|
|
225
|
+
* - Sessions explicitly listed in `excludeSessionIds` are skipped
|
|
226
|
+
* (caller can pass the session the daemon is about to attach to
|
|
227
|
+
* if the ID is known before the sweep).
|
|
228
|
+
* - Absent `lastHeartbeatAt` (never-heartbeated sessions — should
|
|
229
|
+
* only happen for rows created within the last few seconds)
|
|
230
|
+
* treats the session as fresh and skips.
|
|
231
|
+
* - updateSession failures are logged as warnings and don't abort
|
|
232
|
+
* the sweep — best-effort cleanup.
|
|
233
|
+
*
|
|
234
|
+
* Returns the number of sessions actually marked INACTIVE.
|
|
235
|
+
*/
|
|
236
|
+
sweepOrphanSessions(opts: {
|
|
237
|
+
agentType: string;
|
|
238
|
+
staleThresholdMs?: number;
|
|
239
|
+
excludeSessionIds?: string[];
|
|
240
|
+
}): Promise<number>;
|
|
73
241
|
/**
|
|
74
242
|
* List user device keys
|
|
75
243
|
*/
|
|
76
244
|
listUserDeviceKeys(): Promise<DeviceKey[]>;
|
|
245
|
+
/**
|
|
246
|
+
* CP-1.b IMPL r4 H-2 — list BACKEND_SERVICE device keys per design
|
|
247
|
+
* §4.9 schema delta bullet 5 + §6.1 service-device flow.
|
|
248
|
+
*
|
|
249
|
+
* Returns every device row with `kind = BACKEND_SERVICE` regardless of
|
|
250
|
+
* the caller's `userId` (the only such row in CP-1.b is the
|
|
251
|
+
* planner-proxy's ECDH P-256 keypair under `deviceId =
|
|
252
|
+
* planner-proxy-{env}`). Callers union this list with
|
|
253
|
+
* `listUserDeviceKeys()` when minting `encryptedKeys[]` for new
|
|
254
|
+
* sessions so the planner-proxy Lambda can decrypt session-bound
|
|
255
|
+
* payloads via ECDH+HKDF against its own private key.
|
|
256
|
+
*
|
|
257
|
+
* The backend resolver is auth-mode widened (`@aws_cognito_user_pools
|
|
258
|
+
* @aws_iam`) — Cognito callers query for the planner-proxy public key
|
|
259
|
+
* at session-creation time; IAM callers (planner-proxy bootstrap) may
|
|
260
|
+
* also call. The CDK-backed GSI `kind-deviceId-index` partitions the
|
|
261
|
+
* device-keys table by `kind`, so this is a single GSI query, not a
|
|
262
|
+
* full scan.
|
|
263
|
+
*/
|
|
264
|
+
listServiceDeviceKeys(): Promise<DeviceKey[]>;
|
|
77
265
|
/**
|
|
78
266
|
* Register device key
|
|
79
267
|
*/
|
|
@@ -101,6 +289,18 @@ export declare class AppSyncClient {
|
|
|
101
289
|
* derive tier-default reviewer seat assignments.
|
|
102
290
|
*/
|
|
103
291
|
updateAvailableAgents(agents: Array<'CLAUDE' | 'GEMINI' | 'CODEX'>): Promise<UserReviewerPolicySnapshot>;
|
|
292
|
+
/**
|
|
293
|
+
* CP-5.c — push the per-agent capability snapshot. Dual-write
|
|
294
|
+
* alongside `updateAvailableAgents` per LOCK #C5-C-4 (the legacy
|
|
295
|
+
* field stays for V1 client backward compat; this surface carries
|
|
296
|
+
* the full 9-field record per AgentKind).
|
|
297
|
+
*
|
|
298
|
+
* `capabilities` is serialized to JSON before transit (AppSync
|
|
299
|
+
* accepts `AWSJSON` as a stringified payload). Backend Lambda
|
|
300
|
+
* persists to `Users.adapterCapabilities` and returns the updated
|
|
301
|
+
* User row.
|
|
302
|
+
*/
|
|
303
|
+
updateAdapterCapabilities(capabilities: unknown[]): Promise<UserReviewerPolicySnapshot>;
|
|
104
304
|
/**
|
|
105
305
|
* Persist the user's orchestration opt-in default and/or custom
|
|
106
306
|
* reviewer panel. Backend validates seat-count against tier, seat_id
|
|
@@ -109,12 +309,140 @@ export declare class AppSyncClient {
|
|
|
109
309
|
* configure-reviewers wizard).
|
|
110
310
|
*/
|
|
111
311
|
updateReviewerPolicy(input: UpdateReviewerPolicyInput): Promise<UserReviewerPolicySnapshot>;
|
|
312
|
+
/**
|
|
313
|
+
* Fetch the user's subscription tier + status. Used by the Phase 3.a
|
|
314
|
+
* setup wizard (#190) at bootstrap to gate Free → upgrade interstitial
|
|
315
|
+
* and to size the seat budget (Pro=2, Max=3).
|
|
316
|
+
*
|
|
317
|
+
* Backend resolver returns a default FREE row when the user has no
|
|
318
|
+
* Users-table entry yet (Lambda resolver — lambda/subscription/index.ts).
|
|
319
|
+
* Network failure / auth expiry surface as graphqlRequest exceptions.
|
|
320
|
+
*/
|
|
321
|
+
getSubscriptionStatus(): Promise<{
|
|
322
|
+
tier: 'FREE' | 'PRO' | 'MAX';
|
|
323
|
+
status: 'ACTIVE' | 'EXPIRED' | 'GRACE_PERIOD' | 'BILLING_RETRY';
|
|
324
|
+
expiresAt: string | null;
|
|
325
|
+
}>;
|
|
326
|
+
/**
|
|
327
|
+
* CP-1.b IMPL r4 H-1 — `classifyPlannerPrompt` AppSync mutation.
|
|
328
|
+
*
|
|
329
|
+
* Implements `PlannerAppSyncTransport.classifyPlannerPrompt` from
|
|
330
|
+
* `codevibe-core/src/planner/client.ts`. Encrypted-input wire shape
|
|
331
|
+
* is locked at design §4.10 + §4.11: `prompt` is raw base64 AES-GCM
|
|
332
|
+
* ciphertext under the session key; `clarifications`, `sessionContext`,
|
|
333
|
+
* `budgetHint` are AWSJSON envelope strings of the form
|
|
334
|
+
* `'{"encrypted":"<base64 ciphertext>"}'`. Response `decision` is RAW
|
|
335
|
+
* base64 ciphertext (NOT envelope-wrapped) per LOCK #27.
|
|
336
|
+
*
|
|
337
|
+
* Typed errors (`BudgetExceeded`, `TierGateRejected`, etc.) surface
|
|
338
|
+
* via `AppSyncGraphQLError.errorType` so the planner client can
|
|
339
|
+
* discriminate policy events from provider-health failures per
|
|
340
|
+
* Stage 2 r2 M-3.
|
|
341
|
+
*/
|
|
342
|
+
classifyPlannerPrompt(input: {
|
|
343
|
+
sessionId: string;
|
|
344
|
+
prompt: string;
|
|
345
|
+
clarifications: string;
|
|
346
|
+
sessionContext: string;
|
|
347
|
+
budgetHint: string;
|
|
348
|
+
}): Promise<{
|
|
349
|
+
decision: string;
|
|
350
|
+
cacheHit: boolean;
|
|
351
|
+
cacheKind: string | null;
|
|
352
|
+
serverLatencyMs: number;
|
|
353
|
+
providerUsed: string;
|
|
354
|
+
}>;
|
|
355
|
+
/**
|
|
356
|
+
* CP-1.b IMPL r4 H-1 — `pingPlanner` AppSync mutation.
|
|
357
|
+
*
|
|
358
|
+
* Implements `PlannerAppSyncTransport.pingPlanner`. Separate mutation
|
|
359
|
+
* from `classifyPlannerPrompt` per Stage A LOCK #31. Input carries
|
|
360
|
+
* only `sessionId` (no encryption, no clarifications, no budgetHint).
|
|
361
|
+
* Response shape `{ ok, ms }` ONLY (no `providerHealthState` —
|
|
362
|
+
* shell-side `PlannerHealthMachine` is the sole authority).
|
|
363
|
+
*/
|
|
364
|
+
pingPlanner(input: {
|
|
365
|
+
sessionId: string;
|
|
366
|
+
}): Promise<{
|
|
367
|
+
ok: boolean;
|
|
368
|
+
ms: number;
|
|
369
|
+
}>;
|
|
370
|
+
/**
|
|
371
|
+
* CP-8 min Stage 1 R1 HIGH-1 closure (Hendry-approved 2026-05-19).
|
|
372
|
+
*
|
|
373
|
+
* Submits an orchestration gate-prompt decision (Path A FinalApproval
|
|
374
|
+
* or Path B Halted-resolution) to the engine and returns the typed
|
|
375
|
+
* `PostDecisionAction` reply.
|
|
376
|
+
*
|
|
377
|
+
* **Implementation deviation from `PHASE-CP-8-MIN-DESIGN.md` #C8M-6
|
|
378
|
+
* literal wording:** the design says "use `@quantiya/quorum-core`'s
|
|
379
|
+
* `applyUserDecision` SDK method." codevibe-core deliberately does
|
|
380
|
+
* NOT depend on `@quantiya/quorum-core` at runtime — see the
|
|
381
|
+
* structural-typing pattern at `src/orchestration/v1-options.ts:44-47`.
|
|
382
|
+
* The locked INVARIANT of #C8M-6 ("single typed transport surface,
|
|
383
|
+
* no direct GraphQL in the orchestration-shell tree") is honored by
|
|
384
|
+
* exposing this method here on codevibe-core's own AppSyncClient,
|
|
385
|
+
* which is THE desktop-side transport surface. Shape mirrors the
|
|
386
|
+
* quorum-core SDK at `client.ts:464-504` byte-for-byte:
|
|
387
|
+
* - Wraps `notes` (when present) in `EncryptedPayloadInput`
|
|
388
|
+
* (AES-256-GCM under the session key, base64 ciphertext +
|
|
389
|
+
* `sessionId` + `keyVersion`).
|
|
390
|
+
* - Uppercases `decision` to UPPER_SNAKE wire enum (matches the
|
|
391
|
+
* SDK's `toWireEnum` pattern).
|
|
392
|
+
* - Parses the `payload` AWSJSON string to the 4-variant
|
|
393
|
+
* `PostDecisionAction` discriminated union.
|
|
394
|
+
*
|
|
395
|
+
* See `PHASE-CP-8-MIN-DESIGN.md` §4 #C8M-6 deviation footer for the
|
|
396
|
+
* sealed rationale.
|
|
397
|
+
*
|
|
398
|
+
* @param input Caller passes the lowercase TS `decision` kind (one of
|
|
399
|
+
* the 7 `UserDecisionKind` values). Encoding to wire
|
|
400
|
+
* UPPER_SNAKE happens here.
|
|
401
|
+
* @param sessionKeyBase64 Optional. REQUIRED only when `input.notes`
|
|
402
|
+
* is provided — used to AES-GCM-encrypt the notes plaintext
|
|
403
|
+
* under the session key. When `notes` is undefined, this
|
|
404
|
+
* parameter is ignored.
|
|
405
|
+
* @returns Parsed `{ decision, postAction }` per the engine's reply.
|
|
406
|
+
* `decision` is echoed in lowercase TS form for caller
|
|
407
|
+
* ergonomics (e.g. dispatcher routing without re-mapping the
|
|
408
|
+
* UPPER_SNAKE wire value).
|
|
409
|
+
*/
|
|
410
|
+
applyUserDecision(input: {
|
|
411
|
+
gateId: string;
|
|
412
|
+
taskId: string;
|
|
413
|
+
sessionId: string;
|
|
414
|
+
currentRound: number;
|
|
415
|
+
decision: string;
|
|
416
|
+
notes?: string;
|
|
417
|
+
}, sessionKeyBase64?: string): Promise<{
|
|
418
|
+
decision: string;
|
|
419
|
+
postAction: PostDecisionAction;
|
|
420
|
+
}>;
|
|
112
421
|
/**
|
|
113
422
|
* Subscribe to events for a session
|
|
114
423
|
*/
|
|
115
424
|
subscribeToEvents(sessionId: string, onEvent: (event: Event) => void, onError?: (error: Error) => void): () => void;
|
|
116
425
|
/**
|
|
117
426
|
* Build WebSocket URL
|
|
427
|
+
*
|
|
428
|
+
* AppSync exposes the realtime endpoint two different ways depending on
|
|
429
|
+
* the GraphQL endpoint shape:
|
|
430
|
+
*
|
|
431
|
+
* 1. Direct AppSync URL (`<id>.appsync-api.<region>.amazonaws.com`):
|
|
432
|
+
* realtime is on a sibling subdomain — swap `appsync-api` →
|
|
433
|
+
* `appsync-realtime-api` and keep the `/graphql` path.
|
|
434
|
+
* → wss://<id>.appsync-realtime-api.<region>.amazonaws.com/graphql
|
|
435
|
+
*
|
|
436
|
+
* 2. Custom domain (`api.codevibe.quantiya.ai` and friends):
|
|
437
|
+
* realtime is path-based on the SAME hostname — append `/realtime`
|
|
438
|
+
* to the GraphQL path.
|
|
439
|
+
* → wss://api.codevibe.quantiya.ai/graphql/realtime
|
|
440
|
+
* AWS docs:
|
|
441
|
+
* https://docs.aws.amazon.com/appsync/latest/devguide/custom-domain-name.html
|
|
442
|
+
*
|
|
443
|
+
* The naive `.replace('appsync-api', 'appsync-realtime-api')` only works
|
|
444
|
+
* for path 1; on a custom-domain URL it doesn't match anything and the
|
|
445
|
+
* resulting `wss://<custom>/graphql` URL never completes the handshake.
|
|
118
446
|
*/
|
|
119
447
|
private buildRealtimeUrl;
|
|
120
448
|
/**
|
|
@@ -153,6 +481,53 @@ export declare class AppSyncClient {
|
|
|
153
481
|
private sendDeviceKeyWatcherStart;
|
|
154
482
|
private resetDeviceKeyWatcherKeepAlive;
|
|
155
483
|
private handleDeviceKeyWatcherError;
|
|
484
|
+
/**
|
|
485
|
+
* Subscribe to status changes on our own session and invoke
|
|
486
|
+
* onMobileEndRequested when status transitions to INACTIVE — typically
|
|
487
|
+
* meaning the user tapped "End Session" in the mobile app.
|
|
488
|
+
*
|
|
489
|
+
* The callback is invoked from the WebSocket message handler. The
|
|
490
|
+
* helper catches and logs WARN any error thrown by the callback so it
|
|
491
|
+
* does not propagate to the subscription handler (would tear down the
|
|
492
|
+
* WebSocket).
|
|
493
|
+
*
|
|
494
|
+
* Returns a stop() function the plugin MUST call BEFORE issuing its
|
|
495
|
+
* own updateSession({ status: INACTIVE }) mutation in the per-session
|
|
496
|
+
* cleanup handler — otherwise the desktop's own end-of-session
|
|
497
|
+
* mutation echoes back through this subscription as a self-caused
|
|
498
|
+
* callback. See §D.3.a in the design doc. Calling stop() more than
|
|
499
|
+
* once is idempotent.
|
|
500
|
+
*
|
|
501
|
+
* Replace-on-duplicate-sessionId semantics: calling watchForMobileEnd
|
|
502
|
+
* twice with the same sessionId stops the prior watcher and replaces
|
|
503
|
+
* it with the new one, so at most one watcher is alive per sessionId.
|
|
504
|
+
* Matches subscribeToEvents (above). Plugins should still call once
|
|
505
|
+
* per session lifecycle; the replace path exists to make resume /
|
|
506
|
+
* re-entry safe.
|
|
507
|
+
*
|
|
508
|
+
* Initial state assumed = ACTIVE: AppSync subscriptions are
|
|
509
|
+
* mutation-triggered (NOT current-state snapshots), and plugins only
|
|
510
|
+
* call this for sessions just created or resumed in ACTIVE state. The
|
|
511
|
+
* first delivered status=INACTIVE payload IS the real signal and
|
|
512
|
+
* fires the callback.
|
|
513
|
+
*
|
|
514
|
+
* Idempotent firing: callback fires AT MOST ONCE per helper instance.
|
|
515
|
+
* Subsequent INACTIVE payloads (or any payload after fire) are
|
|
516
|
+
* ignored. Plugin must rebuild the helper for a new session.
|
|
517
|
+
*/
|
|
518
|
+
watchForMobileEnd(sessionId: string, onMobileEndRequested: () => Promise<void> | void): {
|
|
519
|
+
stop: () => void;
|
|
520
|
+
};
|
|
521
|
+
private createSessionUpdateWatcherConnection;
|
|
522
|
+
/**
|
|
523
|
+
* Process a delivered onSessionUpdated payload. Decides whether to
|
|
524
|
+
* fire the callback per the locked rules in §A.2 of the design doc.
|
|
525
|
+
*/
|
|
526
|
+
private handleSessionUpdatePayload;
|
|
527
|
+
private sendSessionUpdateWatcherStart;
|
|
528
|
+
private resetSessionUpdateWatcherKeepAlive;
|
|
529
|
+
private handleSessionUpdateWatcherError;
|
|
530
|
+
private cleanupSessionUpdateWatcherState;
|
|
156
531
|
private heartbeatTimers;
|
|
157
532
|
/**
|
|
158
533
|
* Start periodic heartbeat for a session.
|
|
@@ -171,4 +546,41 @@ export declare class AppSyncClient {
|
|
|
171
546
|
* Cleanup all subscriptions and heartbeats
|
|
172
547
|
*/
|
|
173
548
|
cleanupSubscriptions(): void;
|
|
549
|
+
/**
|
|
550
|
+
* Parse a raw `ClassBPacket.packetJson` AWSJSON string into the typed
|
|
551
|
+
* discriminated-union packet. Throws `Error` on malformed input — the caller
|
|
552
|
+
* (subscription handler in CP-2) bridges this to `onError` per §7.2.
|
|
553
|
+
*
|
|
554
|
+
* Exposed for unit testing per design §7.4 row 1
|
|
555
|
+
* (`appsync_client_subscribeToClassBPackets_parses_packetJson_into_typed_packet`).
|
|
556
|
+
*/
|
|
557
|
+
parseClassBPacketPayload(packetJson: string): unknown;
|
|
558
|
+
/**
|
|
559
|
+
* Subscribe to AppSync `onClassBPacket(userId)` and dispatch typed packets
|
|
560
|
+
* to `onPacket`. Errors during parsing OR transport are forwarded to
|
|
561
|
+
* `onError`. Returns an unsubscribe handle.
|
|
562
|
+
*
|
|
563
|
+
* CP-1.e ships the handler surface + parser; full WebSocket wiring on the
|
|
564
|
+
* `subscribeToEvents`-style two-phase reconnect engine completes in CP-2
|
|
565
|
+
* Stage A when the hosted producer side comes online. Until then the method
|
|
566
|
+
* registers the handler and returns a working unsubscribe — callers (the
|
|
567
|
+
* orchestration shell) can wire it during CP-1.e bootstrap with no
|
|
568
|
+
* behavioral change once CP-2 lights up the wire.
|
|
569
|
+
*/
|
|
570
|
+
subscribeToClassBPackets(userId: string, handlers: {
|
|
571
|
+
onPacket: (packet: unknown) => void | Promise<void>;
|
|
572
|
+
onError?: (err: Error) => void;
|
|
573
|
+
}): {
|
|
574
|
+
unsubscribe: () => Promise<void>;
|
|
575
|
+
};
|
|
576
|
+
/**
|
|
577
|
+
* Test seam — deliver a raw envelope payload to the registered handler.
|
|
578
|
+
* Used by §7.4 unit tests to assert parse + forward semantics without
|
|
579
|
+
* standing up a real WebSocket. Production code path (CP-2) will call the
|
|
580
|
+
* same internal flow.
|
|
581
|
+
*
|
|
582
|
+
* @internal
|
|
583
|
+
*/
|
|
584
|
+
_deliverClassBPacketForTests(userId: string, rawPacketJson: string): Promise<void>;
|
|
585
|
+
private readonly classBPacketHandlers;
|
|
174
586
|
}
|
package/dist/appsync/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { AppSyncClient, DownloadUrlResponse } from './appsync-client';
|
|
1
|
+
export { AppSyncClient, AppSyncGraphQLError, DownloadUrlResponse } from './appsync-client';
|
|
2
2
|
export { queries, mutations, subscriptions } from './queries';
|
|
@@ -2,6 +2,16 @@ export declare const queries: {
|
|
|
2
2
|
getSession: string;
|
|
3
3
|
listEvents: string;
|
|
4
4
|
listUserDeviceKeys: string;
|
|
5
|
+
listServiceDeviceKeys: string;
|
|
6
|
+
/**
|
|
7
|
+
* Minimal session listing used by the orphan-sweep path. Only the
|
|
8
|
+
* fields needed to decide whether a session row is stale — sessionId
|
|
9
|
+
* for the INACTIVE mutation, agentType for the per-plugin filter,
|
|
10
|
+
* status to skip non-ACTIVE rows, and lastHeartbeatAt for the age
|
|
11
|
+
* check.
|
|
12
|
+
*/
|
|
13
|
+
listSessions: string;
|
|
14
|
+
getSubscriptionStatus: string;
|
|
5
15
|
};
|
|
6
16
|
export declare const mutations: {
|
|
7
17
|
createSession: string;
|
|
@@ -12,9 +22,14 @@ export declare const mutations: {
|
|
|
12
22
|
grantSessionKey: string;
|
|
13
23
|
getAttachmentDownloadUrl: string;
|
|
14
24
|
updateAvailableAgents: string;
|
|
25
|
+
updateAdapterCapabilities: string;
|
|
15
26
|
updateReviewerPolicy: string;
|
|
27
|
+
classifyPlannerPrompt: string;
|
|
28
|
+
pingPlanner: string;
|
|
29
|
+
applyUserDecision: string;
|
|
16
30
|
};
|
|
17
31
|
export declare const subscriptions: {
|
|
18
32
|
onEventCreated: string;
|
|
19
33
|
onDeviceKeyRegistered: string;
|
|
34
|
+
onSessionUpdated: string;
|
|
20
35
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Typed taxonomy of auth-flow failure reasons.
|
|
3
3
|
*
|
|
4
|
-
* Every value is a sanitized enum literal — never a raw
|
|
5
|
-
* never a truncated user input, never any byte from
|
|
6
|
-
* Adding a new failure mode means extending this
|
|
7
|
-
* then forces every emit site to either use a known
|
|
8
|
-
* a type error.
|
|
4
|
+
* Every value in THIS union is a sanitized enum literal — never a raw
|
|
5
|
+
* error message, never a truncated user input, never any byte from
|
|
6
|
+
* Cognito's response. Adding a new failure mode means extending this
|
|
7
|
+
* union; the compiler then forces every emit site to either use a known
|
|
8
|
+
* value or produce a type error.
|
|
9
|
+
*
|
|
10
|
+
* (Note: the `error_fragment` parameter on the auth_failed beacon DOES
|
|
11
|
+
* carry redacted error material — see `sanitizeAuthErrorFragment`. The
|
|
12
|
+
* `reason` taxonomy below remains the analytics-safe primary key.)
|
|
9
13
|
*
|
|
10
14
|
* Keep values snake_case to match GA4 custom-dimension conventions
|
|
11
15
|
* used elsewhere in the codebase (`step`, `source`, `reason`).
|
|
@@ -29,6 +33,20 @@ export type AuthStage = 'server_start' | 'browser_open' | 'awaiting_callback' |
|
|
|
29
33
|
* address.
|
|
30
34
|
*/
|
|
31
35
|
export declare function fireAuthCompletedBeacon(userId: string): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Bytes 0-99 of the sanitized fragment (GA4 dim: error_fragment).
|
|
38
|
+
* See `sanitizeAuthErrorFragmentFull` for the redaction contract.
|
|
39
|
+
*/
|
|
40
|
+
export declare function sanitizeAuthErrorFragment(msg: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Bytes 100-199 of the sanitized fragment (GA4 dim: error_fragment_2).
|
|
43
|
+
* Returns empty string when the redacted message is ≤100 chars (the
|
|
44
|
+
* typical short-error case), which is what we want — no
|
|
45
|
+
* `error_fragment_2` param fires unless there's something past byte
|
|
46
|
+
* 100 worth carrying. Works around GA4 Measurement Protocol's 100-char
|
|
47
|
+
* per-param limit.
|
|
48
|
+
*/
|
|
49
|
+
export declare function sanitizeAuthErrorFragmentTail(msg: string): string;
|
|
32
50
|
/**
|
|
33
51
|
* Fire the `auth_failed` failure beacon with a sanitized `reason`
|
|
34
52
|
* literal. Optional `httpStatus` captures the numeric HTTP status
|
|
@@ -40,10 +58,29 @@ export declare function fireAuthCompletedBeacon(userId: string): Promise<void>;
|
|
|
40
58
|
* `reason` is constrained to the `AuthFailureReason` union — this
|
|
41
59
|
* is the ONLY input path; passing a raw error message is a compile
|
|
42
60
|
* error.
|
|
61
|
+
*
|
|
62
|
+
* Optional `errorFragment` is a diagnostic dimension reserved for
|
|
63
|
+
* `reason: 'unknown'`. The outer `auth-cli` catch passes the first
|
|
64
|
+
* portion of `error.message` here so the next analytics pass can
|
|
65
|
+
* see what's hiding in `unknown` and we can ship a typed reason in
|
|
66
|
+
* a follow-up. Sanitized inside via `sanitizeAuthErrorFragment` (head)
|
|
67
|
+
* + `sanitizeAuthErrorFragmentTail` (tail) — ANSI stripped, $HOME /
|
|
68
|
+
* USERPROFILE / `/Users/<name>/` / `/home/<name>/` / email substrings
|
|
69
|
+
* redacted (Windows backslashes normalized first so `C:\Users\Alice\…`
|
|
70
|
+
* matches the same path regex as POSIX form), control + non-ASCII
|
|
71
|
+
* bytes dropped, then split into two GA4 dimensions to work around the
|
|
72
|
+
* Measurement Protocol 100-char per-param limit:
|
|
73
|
+
* - `error_fragment` = bytes 0-99
|
|
74
|
+
* - `error_fragment_2` = bytes 100-199 (only set when input >100 chars)
|
|
75
|
+
* Reports concatenate both dims for display. Mirrors the install.sh
|
|
76
|
+
* `sanitize_fragment` / `sanitize_fragment_tail` shell helpers so
|
|
77
|
+
* fragments fired from either path follow the same redaction +
|
|
78
|
+
* slicing contract.
|
|
43
79
|
*/
|
|
44
80
|
export declare function fireAuthFailedBeacon(reason: AuthFailureReason, extra?: {
|
|
45
81
|
httpStatus?: number;
|
|
46
82
|
stage?: AuthStage;
|
|
83
|
+
errorFragment?: string;
|
|
47
84
|
}): Promise<void>;
|
|
48
85
|
/**
|
|
49
86
|
* Attach the reason + beaconed marker to an Error. Non-enumerable so
|
|
@@ -54,3 +91,59 @@ export declare function markErrorBeaconed(err: Error, reason: AuthFailureReason)
|
|
|
54
91
|
export declare function errorWasBeaconed(err: unknown): boolean;
|
|
55
92
|
/** Retrieve the tagged reason from a previously-marked error, if any. */
|
|
56
93
|
export declare function getErrorReason(err: unknown): AuthFailureReason | undefined;
|
|
94
|
+
export type DeviceCountBucket = '0' | '1' | '2-5' | '6+';
|
|
95
|
+
/**
|
|
96
|
+
* Bucket a raw device count into a coarse range to prevent device-count
|
|
97
|
+
* fingerprinting via GA4 client_id stickiness. The `'0'` bucket exists as
|
|
98
|
+
* a safe default for callers that may pass 0; no current emitter actually
|
|
99
|
+
* fires with count 0 in production paths.
|
|
100
|
+
*/
|
|
101
|
+
export declare function bucketDeviceCount(count: number): DeviceCountBucket;
|
|
102
|
+
/**
|
|
103
|
+
* SHA-256-truncate a sessionId for cross-beacon correlation without leaking
|
|
104
|
+
* the raw UUID. 8 hex chars = 32 bits ⇒ no practical reverse lookup absent
|
|
105
|
+
* a GA4 + DDB join.
|
|
106
|
+
*/
|
|
107
|
+
export declare function hashSessionId(sessionId: string): string;
|
|
108
|
+
/**
|
|
109
|
+
* Bug B per-device: fired inside `createSessionKey`'s per-device catch.
|
|
110
|
+
* `session_hash` is optional because keychain-manager intentionally does
|
|
111
|
+
* not know which session is being keyed — the per-session aggregate in
|
|
112
|
+
* `fireSessionEncryptionPartialSuccessBeacon` provides the correlation.
|
|
113
|
+
*/
|
|
114
|
+
export declare function fireSessionEncryptionDeviceSkippedBeacon(params: {
|
|
115
|
+
skipped_count_bucket: DeviceCountBucket;
|
|
116
|
+
session_hash?: string;
|
|
117
|
+
}): Promise<void>;
|
|
118
|
+
/**
|
|
119
|
+
* Bug B per-session: fired once per session creation when at least one
|
|
120
|
+
* device was skipped. Caller MUST gate on `skippedDeviceIds.length > 0`.
|
|
121
|
+
*/
|
|
122
|
+
export declare function fireSessionEncryptionPartialSuccessBeacon(params: {
|
|
123
|
+
session_hash: string;
|
|
124
|
+
encrypted_count_bucket: DeviceCountBucket;
|
|
125
|
+
skipped_count_bucket: DeviceCountBucket;
|
|
126
|
+
}): Promise<void>;
|
|
127
|
+
/**
|
|
128
|
+
* Bug A2: fired when `rekeySessionForNewDevices` grants ≥1 device on resume.
|
|
129
|
+
* Caller MUST gate on `grantedCount > 0`.
|
|
130
|
+
*/
|
|
131
|
+
export declare function fireSessionEncryptionCatchUpGrantBeacon(params: {
|
|
132
|
+
session_hash: string;
|
|
133
|
+
granted_count_bucket: DeviceCountBucket;
|
|
134
|
+
}): Promise<void>;
|
|
135
|
+
/** Bug A1: fired when we enter the self-rekey path (our deviceId missing). */
|
|
136
|
+
export declare function fireSessionEncryptionSelfRekeyRequestBeacon(params: {
|
|
137
|
+
session_hash: string;
|
|
138
|
+
other_device_count_bucket: DeviceCountBucket;
|
|
139
|
+
}): Promise<void>;
|
|
140
|
+
/** Bug A1: fired when polling resolves with our entry + decrypt succeeds. */
|
|
141
|
+
export declare function fireSessionEncryptionSelfRekeySuccessBeacon(params: {
|
|
142
|
+
session_hash: string;
|
|
143
|
+
attempt_count: number;
|
|
144
|
+
}): Promise<void>;
|
|
145
|
+
/** Bug A1: fired when polling exhausts maxAttempts without our entry. */
|
|
146
|
+
export declare function fireSessionEncryptionSelfRekeyTimeoutBeacon(params: {
|
|
147
|
+
session_hash: string;
|
|
148
|
+
attempt_count: number;
|
|
149
|
+
}): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DetectedAgent } from './resolve-agent';
|
|
2
|
+
export interface PickAgentArgs {
|
|
3
|
+
healthy: DetectedAgent[];
|
|
4
|
+
defaultIndex: number;
|
|
5
|
+
/** Test seam — override stdin/stdout. */
|
|
6
|
+
input?: NodeJS.ReadableStream;
|
|
7
|
+
output?: NodeJS.WritableStream;
|
|
8
|
+
}
|
|
9
|
+
export declare function pickAgent(args: PickAgentArgs): Promise<DetectedAgent>;
|