@skrr-ai/cli 0.1.80 → 0.1.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/dist/base-command.d.ts +20 -0
  2. package/dist/base-command.js +151 -7
  3. package/dist/commands/agents/visibility.d.ts +14 -0
  4. package/dist/commands/agents/visibility.js +52 -0
  5. package/dist/commands/create-token.d.ts +0 -1
  6. package/dist/commands/create-token.js +3 -1
  7. package/dist/commands/followups/checkin.js +1 -1
  8. package/dist/commands/list-tokens.d.ts +0 -1
  9. package/dist/commands/list-tokens.js +1 -1
  10. package/dist/commands/login.js +10 -0
  11. package/dist/commands/logout.js +4 -0
  12. package/dist/commands/machines/dedicated/ssh-proxy.js +1 -0
  13. package/dist/commands/revoke-token.d.ts +0 -1
  14. package/dist/commands/revoke-token.js +1 -1
  15. package/dist/commands/store/follow.d.ts +1 -0
  16. package/dist/commands/store/follow.js +7 -1
  17. package/dist/commands/store/follows/list.d.ts +11 -0
  18. package/dist/commands/store/follows/list.js +29 -0
  19. package/dist/commands/store/follows/remove.d.ts +16 -0
  20. package/dist/commands/store/follows/remove.js +37 -0
  21. package/dist/commands/store/installs.js +6 -1
  22. package/dist/commands/store/publishers/profile/draft.d.ts +17 -0
  23. package/dist/commands/store/publishers/profile/draft.js +54 -0
  24. package/dist/commands/store/publishers/profile/handle.d.ts +14 -0
  25. package/dist/commands/store/publishers/profile/handle.js +39 -0
  26. package/dist/commands/store/publishers/profile/hide.d.ts +12 -0
  27. package/dist/commands/store/publishers/profile/hide.js +39 -0
  28. package/dist/commands/store/publishers/profile/preview.d.ts +11 -0
  29. package/dist/commands/store/publishers/profile/preview.js +39 -0
  30. package/dist/commands/store/publishers/profile/publish.d.ts +12 -0
  31. package/dist/commands/store/publishers/profile/publish.js +41 -0
  32. package/dist/commands/store/publishers/profile/restore.d.ts +15 -0
  33. package/dist/commands/store/publishers/profile/restore.js +49 -0
  34. package/dist/commands/store/publishers/profile/revisions.d.ts +11 -0
  35. package/dist/commands/store/publishers/profile/revisions.js +30 -0
  36. package/dist/commands/store/publishers/profile/show.d.ts +11 -0
  37. package/dist/commands/store/publishers/profile/show.js +39 -0
  38. package/dist/commands/store/review.d.ts +26 -0
  39. package/dist/commands/store/review.js +93 -0
  40. package/dist/commands/store/reviews.d.ts +29 -0
  41. package/dist/commands/store/reviews.js +170 -0
  42. package/dist/commands/store/tip.d.ts +20 -0
  43. package/dist/commands/store/tip.js +57 -0
  44. package/dist/commands/tokens/create.d.ts +28 -0
  45. package/dist/commands/tokens/create.js +136 -0
  46. package/dist/commands/tokens/list.d.ts +11 -0
  47. package/dist/commands/tokens/list.js +53 -0
  48. package/dist/commands/tokens/revoke.d.ts +14 -0
  49. package/dist/commands/tokens/revoke.js +42 -0
  50. package/dist/lib/access-tokens.d.ts +59 -0
  51. package/dist/lib/access-tokens.js +50 -0
  52. package/dist/lib/auth-core-init.d.ts +6 -0
  53. package/dist/lib/auth-core-init.js +28 -6
  54. package/dist/lib/auth-storage.d.ts +5 -0
  55. package/dist/lib/auth-storage.js +8 -0
  56. package/dist/lib/config.d.ts +8 -0
  57. package/dist/lib/credential-resolver.d.ts +1 -1
  58. package/dist/lib/credential-resolver.js +15 -3
  59. package/dist/lib/daemonBroker.d.ts +48 -2
  60. package/dist/lib/daemonBroker.js +193 -15
  61. package/dist/lib/daemonBrokerRefusal.d.ts +14 -0
  62. package/dist/lib/daemonBrokerRefusal.js +18 -1
  63. package/dist/lib/dedicated-ssh.d.ts +9 -0
  64. package/dist/lib/dedicated-ssh.js +232 -63
  65. package/dist/lib/harness-context.d.ts +8 -0
  66. package/dist/lib/harness-context.js +55 -0
  67. package/dist/lib/login.js +4 -1
  68. package/dist/lib/node-adapter.js +2 -2
  69. package/dist/lib/publisher-profile-flags.d.ts +19 -0
  70. package/dist/lib/publisher-profile-flags.js +48 -0
  71. package/dist/lib/refresh.d.ts +1 -1
  72. package/dist/lib/refresh.js +10 -1
  73. package/dist/lib/ssh-ordered-bytes.d.ts +8 -0
  74. package/dist/lib/ssh-ordered-bytes.js +31 -0
  75. package/dist/lib/usd-micros.d.ts +9 -0
  76. package/dist/lib/usd-micros.js +21 -0
  77. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialResolver.d.ts +22 -3
  78. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialResolver.js +29 -5
  79. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.d.ts +7 -1
  80. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.js +7 -1
  81. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +2 -2
  82. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +9 -5
  83. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.d.ts +25 -0
  84. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.js +35 -1
  85. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialResolver.d.ts +22 -3
  86. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialResolver.js +27 -4
  87. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.d.ts +7 -1
  88. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.js +7 -1
  89. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +2 -2
  90. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +2 -2
  91. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.d.ts +25 -0
  92. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.js +33 -0
  93. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  94. package/dist/node_modules/@skrr-ai/data-provider/index.js +4302 -4249
  95. package/oclif.manifest.json +41314 -39972
  96. package/package.json +28 -4
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SshOrderedBytes = void 0;
4
+ /** A bounded receiver for a retryable SSH byte stream. One frame may be
5
+ * outstanding. A lost acknowledgment may repeat that exact frame, never its
6
+ * bytes; an overlapping, changed, or skipped frame is a stream error. */
7
+ class SshOrderedBytes {
8
+ nextOffset = 0;
9
+ last;
10
+ receive(offset, bytes, write) {
11
+ if (!Number.isSafeInteger(offset) || offset < 0 || bytes.length < 1 || bytes.length > 16 * 1024 ||
12
+ !Number.isSafeInteger(offset + bytes.length)) {
13
+ return Promise.reject(new Error('invalid SSH stream frame'));
14
+ }
15
+ if (this.last?.offset === offset) {
16
+ return this.last.bytes.equals(bytes)
17
+ ? this.last.written
18
+ : Promise.reject(new Error('changed SSH stream replay'));
19
+ }
20
+ if (offset !== this.nextOffset)
21
+ return Promise.reject(new Error('SSH stream offset mismatch'));
22
+ const retained = Buffer.from(bytes);
23
+ const written = Promise.resolve().then(() => write(retained)).then(() => {
24
+ this.nextOffset = offset + retained.length;
25
+ return this.nextOffset;
26
+ });
27
+ this.last = { offset, bytes: retained, written };
28
+ return written;
29
+ }
30
+ }
31
+ exports.SshOrderedBytes = SshOrderedBytes;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Parse a user-typed USD amount ("5", "2.50") into integer micros.
3
+ *
4
+ * Integer arithmetic on the decimal STRING, never `Number(x) * 1e6`: binary
5
+ * floating point turns 0.29 into 289999.99… and a money path that truncates
6
+ * that charges a micro less — or, rounded the other way, a micro more.
7
+ * Returns null for anything that is not a positive amount with ≤ 2 decimals.
8
+ */
9
+ export declare function usdToMicros(amount: string): number | null;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.usdToMicros = usdToMicros;
4
+ /**
5
+ * Parse a user-typed USD amount ("5", "2.50") into integer micros.
6
+ *
7
+ * Integer arithmetic on the decimal STRING, never `Number(x) * 1e6`: binary
8
+ * floating point turns 0.29 into 289999.99… and a money path that truncates
9
+ * that charges a micro less — or, rounded the other way, a micro more.
10
+ * Returns null for anything that is not a positive amount with ≤ 2 decimals.
11
+ */
12
+ function usdToMicros(amount) {
13
+ const trimmed = amount.trim();
14
+ if (!/^\d+(\.\d{1,2})?$/.test(trimmed))
15
+ return null;
16
+ const [whole, frac = ''] = trimmed.split('.');
17
+ const cents = Number(whole) * 100 + Number(frac.padEnd(2, '0'));
18
+ if (!Number.isSafeInteger(cents) || cents <= 0)
19
+ return null;
20
+ return cents * 10_000;
21
+ }
@@ -13,8 +13,11 @@
13
13
  * Precedence (high → low):
14
14
  *
15
15
  * 1. flag — `--token <jwt>` CLI flag (debugging)
16
- * 2. env-token — `OVERSKY_TOKEN` env (CI / static; Phase I adds
17
- * server-side scope=ci validation)
16
+ * 2. env-token — `OVERSKY_TOKEN` (CI / static). The CLI also reads
17
+ * `SKRR_TOKEN` via `envTokenNames`; `OVERSKY_TOKEN` wins
18
+ * when both are set, matching the CLI config overlay. A
19
+ * personal access token (`osk_pat_*`) is the credential
20
+ * CI should put here.
18
21
  * 3. auth-helper — `OVERSKY_AUTH_HELPER` script output (rotating
19
22
  * creds — Vault, AWS SM, internal SSO proxy)
20
23
  * 4. fd-handoff — `OVERSKY_AUTH_FD` parent→child IPC (Electron
@@ -64,6 +67,12 @@ export interface CredentialResolverOptions {
64
67
  * string to use that value directly.
65
68
  */
66
69
  envTokenOverride?: string | null;
70
+ /**
71
+ * Environment variables read by the env-token slot, in precedence order.
72
+ * Defaults to `['OVERSKY_TOKEN']`. The CLI passes
73
+ * `['OVERSKY_TOKEN', 'SKRR_TOKEN']` (OSK-13208).
74
+ */
75
+ envTokenNames?: readonly string[];
67
76
  /** Test/explicit override for `OVERSKY_AUTH_HELPER` env. Same semantics. */
68
77
  authHelperPathOverride?: string | null;
69
78
  /**
@@ -143,6 +152,8 @@ export interface AuthHelperSentinelInfo {
143
152
  * (POST /api/daemons/token), MUST NOT schedule refresh,
144
153
  * and on auth failure exits 75 with a CI-specific error
145
154
  * rather than writing needs-reauth.json.
155
+ * - 'pat' — personal access token (`osk_pat_*`, OSK-13208): a static
156
+ * bearer used AS the user by the CLI. Never refreshed.
146
157
  * - 'install' — short-lived web-minted JWT with `scope=daemon-install`.
147
158
  * The daemon exchanges it through the same /api/daemons/token
148
159
  * bootstrap path, persists only the returned daemon
@@ -157,9 +168,17 @@ export interface AuthHelperSentinelInfo {
157
168
  * The kill switch `OVERSKY_DISABLE_CI_TOKEN_RESOLVER=1` forces every token to
158
169
  * `'standard'` for triage purposes.
159
170
  */
160
- export type TokenKind = 'standard' | 'ci' | 'install';
171
+ export type TokenKind = 'standard' | 'ci' | 'install' | 'pat';
161
172
  /** CI-token plaintext prefix; mirrors api/server/services/Auth/daemonCiTokens.js. */
162
173
  export declare const CI_TOKEN_PREFIX = "osk_ci_";
174
+ /** Personal-access-token prefix; mirrors api/server/services/Auth/personalAccessTokens.js. */
175
+ export declare const PERSONAL_ACCESS_TOKEN_PREFIX = "osk_pat_";
176
+ /**
177
+ * True for a kind whose token is static by construction: never refreshed,
178
+ * never rotated into a store. Like `TokenKind` itself this selects a local
179
+ * code path and grants nothing.
180
+ */
181
+ export declare function isStaticTokenKind(kind: TokenKind): boolean;
163
182
  /**
164
183
  * Classify a token by local shape. Pure function; safe to call on any string
165
184
  * (including `null`-coerced empty). Returns `'standard'` for empty input
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CredentialResolver = exports.AuthHelperUntrustedError = exports.AuthHelperUnavailableError = exports.CI_TOKEN_PREFIX = exports.CREDENTIAL_PRECEDENCE = void 0;
3
+ exports.CredentialResolver = exports.AuthHelperUntrustedError = exports.AuthHelperUnavailableError = exports.PERSONAL_ACCESS_TOKEN_PREFIX = exports.CI_TOKEN_PREFIX = exports.CREDENTIAL_PRECEDENCE = void 0;
4
+ exports.isStaticTokenKind = isStaticTokenKind;
4
5
  exports.classifyTokenKind = classifyTokenKind;
5
6
  exports.__resetCredentialResolverForTest = __resetCredentialResolverForTest;
6
7
  exports.invalidateAuthHelperCache = invalidateAuthHelperCache;
@@ -19,8 +20,11 @@ exports.invalidateAuthHelperCache = invalidateAuthHelperCache;
19
20
  * Precedence (high → low):
20
21
  *
21
22
  * 1. flag — `--token <jwt>` CLI flag (debugging)
22
- * 2. env-token — `OVERSKY_TOKEN` env (CI / static; Phase I adds
23
- * server-side scope=ci validation)
23
+ * 2. env-token — `OVERSKY_TOKEN` (CI / static). The CLI also reads
24
+ * `SKRR_TOKEN` via `envTokenNames`; `OVERSKY_TOKEN` wins
25
+ * when both are set, matching the CLI config overlay. A
26
+ * personal access token (`osk_pat_*`) is the credential
27
+ * CI should put here.
24
28
  * 3. auth-helper — `OVERSKY_AUTH_HELPER` script output (rotating
25
29
  * creds — Vault, AWS SM, internal SSO proxy)
26
30
  * 4. fd-handoff — `OVERSKY_AUTH_FD` parent→child IPC (Electron
@@ -68,6 +72,16 @@ exports.CREDENTIAL_PRECEDENCE = [
68
72
  ];
69
73
  /** CI-token plaintext prefix; mirrors api/server/services/Auth/daemonCiTokens.js. */
70
74
  exports.CI_TOKEN_PREFIX = 'osk_ci_';
75
+ /** Personal-access-token prefix; mirrors api/server/services/Auth/personalAccessTokens.js. */
76
+ exports.PERSONAL_ACCESS_TOKEN_PREFIX = 'osk_pat_';
77
+ /**
78
+ * True for a kind whose token is static by construction: never refreshed,
79
+ * never rotated into a store. Like `TokenKind` itself this selects a local
80
+ * code path and grants nothing.
81
+ */
82
+ function isStaticTokenKind(kind) {
83
+ return kind === 'ci' || kind === 'pat';
84
+ }
71
85
  /**
72
86
  * Classify a token by local shape. Pure function; safe to call on any string
73
87
  * (including `null`-coerced empty). Returns `'standard'` for empty input
@@ -103,6 +117,8 @@ function classifyTokenKind(token) {
103
117
  return 'standard';
104
118
  if (token.startsWith(exports.CI_TOKEN_PREFIX))
105
119
  return 'ci';
120
+ if (token.startsWith(exports.PERSONAL_ACCESS_TOKEN_PREFIX))
121
+ return 'pat';
106
122
  const payload = (0, jwtUtils_js_1.decodeJwtPayload)(token);
107
123
  if (payload &&
108
124
  typeof payload === 'object' &&
@@ -260,8 +276,16 @@ class CredentialResolver {
260
276
  if (typeof this.opts.envTokenOverride === 'string') {
261
277
  return this.opts.envTokenOverride.length > 0 ? this.opts.envTokenOverride : null;
262
278
  }
263
- const v = process.env.OVERSKY_TOKEN;
264
- return typeof v === 'string' && v.length > 0 ? v : null;
279
+ // `OVERSKY_TOKEN` first (retained by decision, docs/product/skrr-env-inventory.md),
280
+ // then any renamed spelling the caller opted into (`SKRR_TOKEN` for the CLI,
281
+ // OSK-13208). The daemon does not opt in: a CI job that sets `SKRR_TOKEN`
282
+ // for `skrr` must not have a co-located `skrrd` silently adopt it.
283
+ for (const name of this.opts.envTokenNames ?? ['OVERSKY_TOKEN']) {
284
+ const v = process.env[name];
285
+ if (typeof v === 'string' && v.length > 0)
286
+ return v;
287
+ }
288
+ return null;
265
289
  }
266
290
  async tryResolveAuthHelper() {
267
291
  let helperPath;
@@ -38,7 +38,13 @@ export declare function describeDeviceKeySplit(profile: string): {
38
38
  * Order:
39
39
  * 1. Try to load existing keypair from disk.
40
40
  * - Success → state = active.
41
- * - Missing files / corruption / decrypt failure → step 2.
41
+ * - No key material at all (first install) → step 2.
42
+ * - Key material present but unloadable (corruption, decrypt failure,
43
+ * public/private mismatch) → disabled+unreadable_key and a
44
+ * `recovery_required` event, UNLESS `recoverUnreadable` is set. Only
45
+ * an explicit interactive login sets it, because that login proves and
46
+ * re-pins the new key; replacing it on ordinary boot would sign the
47
+ * next refresh with a key the server never pinned.
42
48
  * 2. Generate fresh keypair and persist. Failure to persist is a hard
43
49
  * error landing in disabled+persist_failed.
44
50
  */
@@ -355,7 +355,13 @@ async function consolidateDeviceIdentity(profile) {
355
355
  * Order:
356
356
  * 1. Try to load existing keypair from disk.
357
357
  * - Success → state = active.
358
- * - Missing files / corruption / decrypt failure → step 2.
358
+ * - No key material at all (first install) → step 2.
359
+ * - Key material present but unloadable (corruption, decrypt failure,
360
+ * public/private mismatch) → disabled+unreadable_key and a
361
+ * `recovery_required` event, UNLESS `recoverUnreadable` is set. Only
362
+ * an explicit interactive login sets it, because that login proves and
363
+ * re-pins the new key; replacing it on ordinary boot would sign the
364
+ * next refresh with a key the server never pinned.
359
365
  * 2. Generate fresh keypair and persist. Failure to persist is a hard
360
366
  * error landing in disabled+persist_failed.
361
367
  */
@@ -16,7 +16,7 @@ export { classifyRefreshResponse, type RefreshResponseShape, type ClassifiedRefr
16
16
  export { refreshDaemonToken, revokeDaemonRefreshSession, withAuthLock, persistReauthState, needsReauthState, clearReauthState, installLockExitHandlers, __refreshDiagnostics, __resetUnknown401StreaksForTest, UNKNOWN_401_BUDGET, } from './refresh.js';
17
17
  export { createRefreshScheduler, type RefreshScheduler, type RefreshSchedulerOptions, } from './refreshScheduler.js';
18
18
  export { readAuthFromFd, __setFdReaderForTest, type FdAuthPayload } from './fdToken.js';
19
- export { CredentialResolver, CREDENTIAL_PRECEDENCE, __resetCredentialResolverForTest, invalidateAuthHelperCache, classifyTokenKind, CI_TOKEN_PREFIX, AuthHelperUntrustedError, AuthHelperUnavailableError, type CredentialSource, type CredentialStoreMode, type CredentialResolverOptions, type ResolvedCredential, type TokenKind, type HelperTrustDecision, type AuthHelperBlockedInfo, type AuthHelperSentinelInfo, } from './credentialResolver.js';
19
+ export { CredentialResolver, CREDENTIAL_PRECEDENCE, __resetCredentialResolverForTest, invalidateAuthHelperCache, classifyTokenKind, CI_TOKEN_PREFIX, PERSONAL_ACCESS_TOKEN_PREFIX, isStaticTokenKind, AuthHelperUntrustedError, AuthHelperUnavailableError, type CredentialSource, type CredentialStoreMode, type CredentialResolverOptions, type ResolvedCredential, type TokenKind, type HelperTrustDecision, type AuthHelperBlockedInfo, type AuthHelperSentinelInfo, } from './credentialResolver.js';
20
20
  export { invokeAuthHelper, getDefaultHelperTtlMs, getLastAuthHelperFailureReason, __resetAuthHelperFailureReasonForTest, SENTINEL_TRIGGERING_FAILURES, type HelperResult, type InvokeAuthHelperOptions, type AuthHelperFailureReason, } from './authHelper.js';
21
21
  export { runHeadersHelper, invalidateHeadersHelperCache, type RunHeadersHelperOptions, } from './headers-helper.js';
22
22
  export { generateVerifier, challenge, generateState, safeEqual, verifyChallenge, type PkceChallengeMethod, } from './pkce.js';
@@ -35,7 +35,7 @@ export { ensureMachineDaemonId, legacyDaemonUuids, __resetCachedDaemonIdForTest,
35
35
  export { PAIR_AAD_PREFIX, PAIR_AAD_MAX_LEN, PAIR_BUNDLE_MAX_BASE64_LEN, PAIR_NONCE_LEN, PAIR_PUBKEY_LEN, PAIR_SECRET_LEN, PairBundleError, assemblePairBundleBase64, base64ToUint8Array as pairBase64ToUint8Array, base64UrlToUint8Array as pairBase64UrlToUint8Array, buildPairAad, buildPairUrl, generatePairKeyPair, openPairBundleBase64, parsePairBundle, parsePairPlaintext, parsePairUrl, uint8ArrayToBase64 as pairUint8ArrayToBase64, uint8ArrayToBase64Url as pairUint8ArrayToBase64Url, type AssembleBundleOptions as PairAssembleBundleOptions, type OpenBundleOptions as PairOpenBundleOptions, type PairBundle, type PairBundleErrorCode, type PairKeyPair, type PairPlaintextV1, type PairUrlFields, } from './daemonPair.js';
36
36
  export { HARNESS_TIERS, getHarnessTier, credentialPolicyForTier, tierPermitsConfiguredAutoMode, type HarnessTrustTier, type CredentialDeliveryPolicy, type CredentialMode, } from './harnessTrust.js';
37
37
  export { HARNESSES_LOADING_CLAUDE_SKILLS_LAYOUT, claudeSkillsLayoutEvidence, harnessLoadsClaudeSkillsLayout, } from './harnessSkillLayout.js';
38
- export { sanitizeSpawnEnv, SENSITIVE_ENV_VARS, SENSITIVE_ENV_PREFIXES, SENSITIVE_ENV_SUFFIXES, SENSITIVE_ENV_NAME_TOKENS, SENSITIVE_ENV_PREFIX_EXCEPTIONS, LOOPBACK_NO_PROXY_HOSTS, envHasProxy, withLoopbackNoProxy, } from './spawnEnv.js';
38
+ export { sanitizeSpawnEnv, SENSITIVE_ENV_VARS, SENSITIVE_ENV_PREFIXES, SENSITIVE_ENV_SUFFIXES, SENSITIVE_ENV_NAME_TOKENS, SENSITIVE_ENV_PREFIX_EXCEPTIONS, DAEMON_CHILD_ENV, isDaemonChildEnv, LOOPBACK_NO_PROXY_HOSTS, envHasProxy, withLoopbackNoProxy, } from './spawnEnv.js';
39
39
  export { loopbackFetch, assertLoopbackHttpUrl, isLoopbackHostname, isLoopbackAddress, LoopbackTargetRefusedError, LOOPBACK_DEFAULT_MAX_BODY_BYTES, type LoopbackFetch, type LoopbackFetchInit, } from './loopbackHttp.js';
40
40
  export { CONFIG_DIR_NAME, LEGACY_CONFIG_DIR_NAMES, NATIVE_ID_PREFIX, LEGACY_NATIVE_ID_PREFIXES, DEFAULT_BINARY_NAME, } from './localIdentity.js';
41
41
  export { findLegacyLocalState, describeLegacyState, type LegacyStateFinding, type LegacyStateReport, } from './legacyStatePreflight.js';
@@ -22,11 +22,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
22
22
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
23
23
  };
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.generateVerifier = exports.invalidateHeadersHelperCache = exports.runHeadersHelper = exports.SENTINEL_TRIGGERING_FAILURES = exports.__resetAuthHelperFailureReasonForTest = exports.getLastAuthHelperFailureReason = exports.getDefaultHelperTtlMs = exports.invokeAuthHelper = exports.AuthHelperUnavailableError = exports.AuthHelperUntrustedError = exports.CI_TOKEN_PREFIX = exports.classifyTokenKind = exports.invalidateAuthHelperCache = exports.__resetCredentialResolverForTest = exports.CREDENTIAL_PRECEDENCE = exports.CredentialResolver = exports.__setFdReaderForTest = exports.readAuthFromFd = exports.createRefreshScheduler = exports.UNKNOWN_401_BUDGET = exports.__resetUnknown401StreaksForTest = exports.__refreshDiagnostics = exports.installLockExitHandlers = exports.clearReauthState = exports.needsReauthState = exports.persistReauthState = exports.withAuthLock = exports.revokeDaemonRefreshSession = exports.refreshDaemonToken = exports.classifyRefreshResponse = exports.EXIT_NEEDS_REAUTH = exports.reauthCommand = exports.formatReauthMessage = exports.handleMidStreamAuthExpiry = exports.isAuthExpiredSseEvent = exports.decodeJwtPayload = exports.decodeJwtExpiry = exports.TransientAuthFailure = exports.PermanentAuthFailure = exports.emitAuthTelemetry = exports.getAuthBinaryName = exports.getAuthKillSwitches = exports.getAuthConfigDir = exports.getAuthLogger = exports.configureAuthCore = exports.OAUTH_CLI_SCOPE = exports.isDaemonScope = exports.VALID_DAEMON_SCOPE_SET = exports.ALL_DAEMON_SCOPES = exports.SCOPES = void 0;
26
- exports.publicJwkFromX = exports.normalizeHtu = exports.jwkThumbprint = exports.generateDeviceKeyPair = exports.buildDeviceProof = exports.zeroizeKekCaches = exports.WindowsKek = exports.registerZeroizeHook = exports.MacosKek = exports.LinuxKek = exports.KekUnavailableError = exports.UnavailableKek = exports.InMemoryKek = exports.getKekStrategy = exports.__setKekStrategyForTest = exports.credEnvelopeWrap = exports.credEnvelopeUnwrap = exports.credEnvelopeSerialize = exports.credSealBuffer = exports.credOpenBuffer = exports.CRED_KEY_LEN = exports.isCredEnvelopeString = exports.generateDek = exports.CRED_ENVELOPE_MAGIC = exports.credEnvelopeEncrypt = exports.credEnvelopeDeserialize = exports.credEnvelopeDecrypt = exports.buildCredentialAad = exports.isValidRecoveryCode = exports.normalizeRecoveryCode = exports.parseRecoveryCode = exports.formatRecoveryCode = exports.MAX_TTL_DAYS = exports.MIN_TTL_DAYS = exports.parseTtlDays = exports.LoginExchangeError = exports.LoginInitError = exports.loginWithLocalhost = exports.LocalCallbackMalformedError = exports.LocalCallbackDeniedError = exports.LocalCallbackStateMismatchError = exports.LocalCallbackTimeoutError = exports.LocalCallbackBindError = exports.LocalCallbackError = exports.DEFAULT_LOGIN_TIMEOUT_MS = exports.startLocalCallback = exports.verifyChallenge = exports.safeEqual = exports.generateState = exports.challenge = void 0;
27
- exports.__resetCachedDaemonIdForTest = exports.legacyDaemonUuids = exports.ensureMachineDaemonId = exports.__resetMachineUuidCacheForTest = exports.HOSTED_RUNTIME_MACHINE_SOURCES = exports.hostedRuntimeIdOverride = exports.getMachineUuid = exports.__getDeviceIdentityStateForTest = exports.__setDeviceIdentityStateForTest = exports.__enrollmentBackoffPathForTest = exports.__enrollmentMarkerPathForTest = exports.__privateKeyPathForTest = exports.__publicKeyPathForTest = exports.describeDeviceKeySplit = exports.describeDeviceIdentityState = exports.getDevicePublicKey = exports.isDeviceIdentityActive = exports.clearEnrollmentMarker = exports.enrollWithServer = exports.signServerRequest = exports.resetDeviceIdentity = exports.initDeviceIdentity = exports.__resetShutdownGuardForTest = exports.__getCredEnvelopeStateForTest = exports.__setCredEnvelopeStateForTest = exports.__wrappedDekFilePathForTest = exports.DEFAULT_UNREADABLE_CREDENTIAL_HINT = exports.maybeDecryptOnRead = exports.maybeEncryptForWrite = exports.splitKeyConvergencePolicy = exports.describeCredEnvelopeState = exports.hasCredEnvelopePathConflict = exports.isCredEnvelopeActive = exports.shutdownCredEnvelope = exports.resetCredEnvelope = exports.initCredEnvelope = exports.verifyDpopProof = exports.normalizeDpopHtu = exports.isJwkThumbprint = exports.isAth = exports.createDpopKey = exports.accessTokenHash = exports.DPOP_PROOF_VERIFY_UNAVAILABLE = exports.DPOP_PROOF_TYP = exports.DPOP_PROOF_REQUIRED = exports.DPOP_PROOF_INVALID = exports.DPOP_MAX_AGE_SECONDS = exports.DPOP_HEADER = exports.verifyDeviceProof = exports.tokenHash = void 0;
28
- exports.FIRST_PARTY_HARNESS_PROVENANCE_SUFFIX = exports.FIRST_PARTY_HARNESS_PREVIOUS_SUFFIX = exports.describeLegacyState = exports.findLegacyLocalState = exports.DEFAULT_BINARY_NAME = exports.LEGACY_NATIVE_ID_PREFIXES = exports.NATIVE_ID_PREFIX = exports.LEGACY_CONFIG_DIR_NAMES = exports.CONFIG_DIR_NAME = exports.LOOPBACK_DEFAULT_MAX_BODY_BYTES = exports.LoopbackTargetRefusedError = exports.isLoopbackAddress = exports.isLoopbackHostname = exports.assertLoopbackHttpUrl = exports.loopbackFetch = exports.withLoopbackNoProxy = exports.envHasProxy = exports.LOOPBACK_NO_PROXY_HOSTS = exports.SENSITIVE_ENV_PREFIX_EXCEPTIONS = exports.SENSITIVE_ENV_NAME_TOKENS = exports.SENSITIVE_ENV_SUFFIXES = exports.SENSITIVE_ENV_PREFIXES = exports.SENSITIVE_ENV_VARS = exports.sanitizeSpawnEnv = exports.harnessLoadsClaudeSkillsLayout = exports.claudeSkillsLayoutEvidence = exports.HARNESSES_LOADING_CLAUDE_SKILLS_LAYOUT = exports.tierPermitsConfiguredAutoMode = exports.credentialPolicyForTier = exports.getHarnessTier = exports.HARNESS_TIERS = exports.pairUint8ArrayToBase64Url = exports.pairUint8ArrayToBase64 = exports.parsePairUrl = exports.parsePairPlaintext = exports.parsePairBundle = exports.openPairBundleBase64 = exports.generatePairKeyPair = exports.buildPairUrl = exports.buildPairAad = exports.pairBase64UrlToUint8Array = exports.pairBase64ToUint8Array = exports.assemblePairBundleBase64 = exports.PairBundleError = exports.PAIR_SECRET_LEN = exports.PAIR_PUBKEY_LEN = exports.PAIR_NONCE_LEN = exports.PAIR_BUNDLE_MAX_BASE64_LEN = exports.PAIR_AAD_MAX_LEN = exports.PAIR_AAD_PREFIX = void 0;
29
- exports.consolidateProfileState = exports.profileStateFilePathsToClear = exports.profileStateFileLocations = exports.resolveProfileStateFile = exports.resolveProfileStateDir = exports.legacyProfileStateDir = exports.profileStateDir = exports.SUPERSEDED_COPY_SUFFIX = exports.SUPERSEDED_MARKER_SUFFIX = exports.PROFILES_SEGMENT = exports.isConfigRootOverridden = exports.configRootPath = exports.resolveConfigRoot = exports.verifyManifest = exports.verifyArtifact = exports.isTrustedArtifactOrigin = exports.getDeltaFor = exports.buildManifestMessage = exports.buildArtifactMessage = exports.TRUSTED_FEED_ORIGINS = exports.MAX_SIGS = exports.OVERSKY_RELEASE_PUBLIC_KEYS = exports.resolveFirstPartyHarnessChannel = exports.resolveChannelManifestUrl = exports.isFirstPartyHarnessChannel = exports.firstPartyHarnessFeedCandidates = exports.firstPartyHarnessFeedBase = exports.firstPartyHarnessChannelPrefix = exports.FIRST_PARTY_HARNESS_CHANNELS = exports.DEFAULT_FIRST_PARTY_HARNESS_CHANNEL = exports.migrateFirstPartyHarnessHome = exports.linkFirstPartyHarnessAliases = exports.firstPartyHarnessInstalledBinaryPath = exports.firstPartyHarnessHomeDir = exports.firstPartyHarnessBinDir = void 0;
25
+ exports.runHeadersHelper = exports.SENTINEL_TRIGGERING_FAILURES = exports.__resetAuthHelperFailureReasonForTest = exports.getLastAuthHelperFailureReason = exports.getDefaultHelperTtlMs = exports.invokeAuthHelper = exports.AuthHelperUnavailableError = exports.AuthHelperUntrustedError = exports.isStaticTokenKind = exports.PERSONAL_ACCESS_TOKEN_PREFIX = exports.CI_TOKEN_PREFIX = exports.classifyTokenKind = exports.invalidateAuthHelperCache = exports.__resetCredentialResolverForTest = exports.CREDENTIAL_PRECEDENCE = exports.CredentialResolver = exports.__setFdReaderForTest = exports.readAuthFromFd = exports.createRefreshScheduler = exports.UNKNOWN_401_BUDGET = exports.__resetUnknown401StreaksForTest = exports.__refreshDiagnostics = exports.installLockExitHandlers = exports.clearReauthState = exports.needsReauthState = exports.persistReauthState = exports.withAuthLock = exports.revokeDaemonRefreshSession = exports.refreshDaemonToken = exports.classifyRefreshResponse = exports.EXIT_NEEDS_REAUTH = exports.reauthCommand = exports.formatReauthMessage = exports.handleMidStreamAuthExpiry = exports.isAuthExpiredSseEvent = exports.decodeJwtPayload = exports.decodeJwtExpiry = exports.TransientAuthFailure = exports.PermanentAuthFailure = exports.emitAuthTelemetry = exports.getAuthBinaryName = exports.getAuthKillSwitches = exports.getAuthConfigDir = exports.getAuthLogger = exports.configureAuthCore = exports.OAUTH_CLI_SCOPE = exports.isDaemonScope = exports.VALID_DAEMON_SCOPE_SET = exports.ALL_DAEMON_SCOPES = exports.SCOPES = void 0;
26
+ exports.jwkThumbprint = exports.generateDeviceKeyPair = exports.buildDeviceProof = exports.zeroizeKekCaches = exports.WindowsKek = exports.registerZeroizeHook = exports.MacosKek = exports.LinuxKek = exports.KekUnavailableError = exports.UnavailableKek = exports.InMemoryKek = exports.getKekStrategy = exports.__setKekStrategyForTest = exports.credEnvelopeWrap = exports.credEnvelopeUnwrap = exports.credEnvelopeSerialize = exports.credSealBuffer = exports.credOpenBuffer = exports.CRED_KEY_LEN = exports.isCredEnvelopeString = exports.generateDek = exports.CRED_ENVELOPE_MAGIC = exports.credEnvelopeEncrypt = exports.credEnvelopeDeserialize = exports.credEnvelopeDecrypt = exports.buildCredentialAad = exports.isValidRecoveryCode = exports.normalizeRecoveryCode = exports.parseRecoveryCode = exports.formatRecoveryCode = exports.MAX_TTL_DAYS = exports.MIN_TTL_DAYS = exports.parseTtlDays = exports.LoginExchangeError = exports.LoginInitError = exports.loginWithLocalhost = exports.LocalCallbackMalformedError = exports.LocalCallbackDeniedError = exports.LocalCallbackStateMismatchError = exports.LocalCallbackTimeoutError = exports.LocalCallbackBindError = exports.LocalCallbackError = exports.DEFAULT_LOGIN_TIMEOUT_MS = exports.startLocalCallback = exports.verifyChallenge = exports.safeEqual = exports.generateState = exports.challenge = exports.generateVerifier = exports.invalidateHeadersHelperCache = void 0;
27
+ exports.ensureMachineDaemonId = exports.__resetMachineUuidCacheForTest = exports.HOSTED_RUNTIME_MACHINE_SOURCES = exports.hostedRuntimeIdOverride = exports.getMachineUuid = exports.__getDeviceIdentityStateForTest = exports.__setDeviceIdentityStateForTest = exports.__enrollmentBackoffPathForTest = exports.__enrollmentMarkerPathForTest = exports.__privateKeyPathForTest = exports.__publicKeyPathForTest = exports.describeDeviceKeySplit = exports.describeDeviceIdentityState = exports.getDevicePublicKey = exports.isDeviceIdentityActive = exports.clearEnrollmentMarker = exports.enrollWithServer = exports.signServerRequest = exports.resetDeviceIdentity = exports.initDeviceIdentity = exports.__resetShutdownGuardForTest = exports.__getCredEnvelopeStateForTest = exports.__setCredEnvelopeStateForTest = exports.__wrappedDekFilePathForTest = exports.DEFAULT_UNREADABLE_CREDENTIAL_HINT = exports.maybeDecryptOnRead = exports.maybeEncryptForWrite = exports.splitKeyConvergencePolicy = exports.describeCredEnvelopeState = exports.hasCredEnvelopePathConflict = exports.isCredEnvelopeActive = exports.shutdownCredEnvelope = exports.resetCredEnvelope = exports.initCredEnvelope = exports.verifyDpopProof = exports.normalizeDpopHtu = exports.isJwkThumbprint = exports.isAth = exports.createDpopKey = exports.accessTokenHash = exports.DPOP_PROOF_VERIFY_UNAVAILABLE = exports.DPOP_PROOF_TYP = exports.DPOP_PROOF_REQUIRED = exports.DPOP_PROOF_INVALID = exports.DPOP_MAX_AGE_SECONDS = exports.DPOP_HEADER = exports.verifyDeviceProof = exports.tokenHash = exports.publicJwkFromX = exports.normalizeHtu = void 0;
28
+ exports.DEFAULT_BINARY_NAME = exports.LEGACY_NATIVE_ID_PREFIXES = exports.NATIVE_ID_PREFIX = exports.LEGACY_CONFIG_DIR_NAMES = exports.CONFIG_DIR_NAME = exports.LOOPBACK_DEFAULT_MAX_BODY_BYTES = exports.LoopbackTargetRefusedError = exports.isLoopbackAddress = exports.isLoopbackHostname = exports.assertLoopbackHttpUrl = exports.loopbackFetch = exports.withLoopbackNoProxy = exports.envHasProxy = exports.LOOPBACK_NO_PROXY_HOSTS = exports.isDaemonChildEnv = exports.DAEMON_CHILD_ENV = exports.SENSITIVE_ENV_PREFIX_EXCEPTIONS = exports.SENSITIVE_ENV_NAME_TOKENS = exports.SENSITIVE_ENV_SUFFIXES = exports.SENSITIVE_ENV_PREFIXES = exports.SENSITIVE_ENV_VARS = exports.sanitizeSpawnEnv = exports.harnessLoadsClaudeSkillsLayout = exports.claudeSkillsLayoutEvidence = exports.HARNESSES_LOADING_CLAUDE_SKILLS_LAYOUT = exports.tierPermitsConfiguredAutoMode = exports.credentialPolicyForTier = exports.getHarnessTier = exports.HARNESS_TIERS = exports.pairUint8ArrayToBase64Url = exports.pairUint8ArrayToBase64 = exports.parsePairUrl = exports.parsePairPlaintext = exports.parsePairBundle = exports.openPairBundleBase64 = exports.generatePairKeyPair = exports.buildPairUrl = exports.buildPairAad = exports.pairBase64UrlToUint8Array = exports.pairBase64ToUint8Array = exports.assemblePairBundleBase64 = exports.PairBundleError = exports.PAIR_SECRET_LEN = exports.PAIR_PUBKEY_LEN = exports.PAIR_NONCE_LEN = exports.PAIR_BUNDLE_MAX_BASE64_LEN = exports.PAIR_AAD_MAX_LEN = exports.PAIR_AAD_PREFIX = exports.__resetCachedDaemonIdForTest = exports.legacyDaemonUuids = void 0;
29
+ exports.consolidateProfileState = exports.profileStateFilePathsToClear = exports.profileStateFileLocations = exports.resolveProfileStateFile = exports.resolveProfileStateDir = exports.legacyProfileStateDir = exports.profileStateDir = exports.SUPERSEDED_COPY_SUFFIX = exports.SUPERSEDED_MARKER_SUFFIX = exports.PROFILES_SEGMENT = exports.isConfigRootOverridden = exports.configRootPath = exports.resolveConfigRoot = exports.verifyManifest = exports.verifyArtifact = exports.isTrustedArtifactOrigin = exports.getDeltaFor = exports.buildManifestMessage = exports.buildArtifactMessage = exports.TRUSTED_FEED_ORIGINS = exports.MAX_SIGS = exports.OVERSKY_RELEASE_PUBLIC_KEYS = exports.resolveFirstPartyHarnessChannel = exports.resolveChannelManifestUrl = exports.isFirstPartyHarnessChannel = exports.firstPartyHarnessFeedCandidates = exports.firstPartyHarnessFeedBase = exports.firstPartyHarnessChannelPrefix = exports.FIRST_PARTY_HARNESS_CHANNELS = exports.DEFAULT_FIRST_PARTY_HARNESS_CHANNEL = exports.migrateFirstPartyHarnessHome = exports.linkFirstPartyHarnessAliases = exports.firstPartyHarnessInstalledBinaryPath = exports.firstPartyHarnessHomeDir = exports.firstPartyHarnessBinDir = exports.FIRST_PARTY_HARNESS_PROVENANCE_SUFFIX = exports.FIRST_PARTY_HARNESS_PREVIOUS_SUFFIX = exports.describeLegacyState = exports.findLegacyLocalState = void 0;
30
30
  // Daemon scope vocabulary — single source of truth for non-Mongoose tiers
31
31
  // (daemon, desktop, cli). Schema-bound canonical lives in
32
32
  // `@skrr-ai/data-schemas/common/daemonScopes`; the two are kept byte-equal
@@ -109,6 +109,8 @@ Object.defineProperty(exports, "__resetCredentialResolverForTest", { enumerable:
109
109
  Object.defineProperty(exports, "invalidateAuthHelperCache", { enumerable: true, get: function () { return credentialResolver_js_1.invalidateAuthHelperCache; } });
110
110
  Object.defineProperty(exports, "classifyTokenKind", { enumerable: true, get: function () { return credentialResolver_js_1.classifyTokenKind; } });
111
111
  Object.defineProperty(exports, "CI_TOKEN_PREFIX", { enumerable: true, get: function () { return credentialResolver_js_1.CI_TOKEN_PREFIX; } });
112
+ Object.defineProperty(exports, "PERSONAL_ACCESS_TOKEN_PREFIX", { enumerable: true, get: function () { return credentialResolver_js_1.PERSONAL_ACCESS_TOKEN_PREFIX; } });
113
+ Object.defineProperty(exports, "isStaticTokenKind", { enumerable: true, get: function () { return credentialResolver_js_1.isStaticTokenKind; } });
112
114
  // L6.1 / L6.3 — fail-closed errors thrown by the auth-helper slot.
113
115
  Object.defineProperty(exports, "AuthHelperUntrustedError", { enumerable: true, get: function () { return credentialResolver_js_1.AuthHelperUntrustedError; } });
114
116
  Object.defineProperty(exports, "AuthHelperUnavailableError", { enumerable: true, get: function () { return credentialResolver_js_1.AuthHelperUnavailableError; } });
@@ -344,6 +346,8 @@ Object.defineProperty(exports, "SENSITIVE_ENV_PREFIXES", { enumerable: true, get
344
346
  Object.defineProperty(exports, "SENSITIVE_ENV_SUFFIXES", { enumerable: true, get: function () { return spawnEnv_js_1.SENSITIVE_ENV_SUFFIXES; } });
345
347
  Object.defineProperty(exports, "SENSITIVE_ENV_NAME_TOKENS", { enumerable: true, get: function () { return spawnEnv_js_1.SENSITIVE_ENV_NAME_TOKENS; } });
346
348
  Object.defineProperty(exports, "SENSITIVE_ENV_PREFIX_EXCEPTIONS", { enumerable: true, get: function () { return spawnEnv_js_1.SENSITIVE_ENV_PREFIX_EXCEPTIONS; } });
349
+ Object.defineProperty(exports, "DAEMON_CHILD_ENV", { enumerable: true, get: function () { return spawnEnv_js_1.DAEMON_CHILD_ENV; } });
350
+ Object.defineProperty(exports, "isDaemonChildEnv", { enumerable: true, get: function () { return spawnEnv_js_1.isDaemonChildEnv; } });
347
351
  Object.defineProperty(exports, "LOOPBACK_NO_PROXY_HOSTS", { enumerable: true, get: function () { return spawnEnv_js_1.LOOPBACK_NO_PROXY_HOSTS; } });
348
352
  Object.defineProperty(exports, "envHasProxy", { enumerable: true, get: function () { return spawnEnv_js_1.envHasProxy; } });
349
353
  Object.defineProperty(exports, "withLoopbackNoProxy", { enumerable: true, get: function () { return spawnEnv_js_1.withLoopbackNoProxy; } });
@@ -77,6 +77,31 @@ export declare const SENSITIVE_ENV_SUFFIXES: readonly string[];
77
77
  export declare const SENSITIVE_ENV_NAME_TOKENS: readonly string[];
78
78
  /** Specific names to keep — the prefix sweeps are broad on purpose. */
79
79
  export declare const SENSITIVE_ENV_PREFIX_EXCEPTIONS: ReadonlySet<string>;
80
+ /**
81
+ * OSK-13254 — the marker the daemon stamps on every agent- or tool-driven child
82
+ * (`daemon/src/env-sanitize.ts`, `daemon/src/terminal/agent-terminal-env.ts`).
83
+ *
84
+ * A `skrr` that sees it is a borrower: it redeems short-lived tokens from the
85
+ * daemon's loopback broker, never adopts a CLI refresh session of its own, and
86
+ * never reads the person's stored one (`cli/src/lib/harness-context.ts`). A
87
+ * person's own terminal — including the web terminal, which is a human surface
88
+ * (`humanTerminalEnv`) — does not carry it.
89
+ *
90
+ * The marker can only take authority away, so a process that forges it hurts
91
+ * nobody but itself. On a laptop it is POLICY, not a boundary: a same-uid child
92
+ * that deletes it can do whatever the person's own shell can. Where a uid
93
+ * boundary exists (Dedicated Runtime, identity-split Hosted Machines), the
94
+ * guest descriptor already offers only the access-token mode, so a durable CLI
95
+ * family cannot be minted there whatever the environment says.
96
+ */
97
+ export declare const DAEMON_CHILD_ENV = "SKRR_DAEMON_CHILD";
98
+ /**
99
+ * True when `env` carries the daemon-child marker with ANY non-empty value.
100
+ * Deliberately no "0 means off": the marker only narrows authority, so the
101
+ * one value that could switch it off is the one a request-carried environment
102
+ * would forge.
103
+ */
104
+ export declare function isDaemonChildEnv(env: Readonly<Record<string, string | undefined>>): boolean;
80
105
  /**
81
106
  * Build a sanitized snapshot of the parent's own env for a spawned
82
107
  * child, stripping credentials and library-injection vectors while
@@ -40,7 +40,8 @@
40
40
  * serve that case: a deny-list with a hole is not a deny-list.
41
41
  */
42
42
  Object.defineProperty(exports, "__esModule", { value: true });
43
- exports.LOOPBACK_NO_PROXY_HOSTS = exports.SENSITIVE_ENV_PREFIX_EXCEPTIONS = exports.SENSITIVE_ENV_NAME_TOKENS = exports.SENSITIVE_ENV_SUFFIXES = exports.SENSITIVE_ENV_PREFIXES = exports.SENSITIVE_ENV_VARS = void 0;
43
+ exports.LOOPBACK_NO_PROXY_HOSTS = exports.DAEMON_CHILD_ENV = exports.SENSITIVE_ENV_PREFIX_EXCEPTIONS = exports.SENSITIVE_ENV_NAME_TOKENS = exports.SENSITIVE_ENV_SUFFIXES = exports.SENSITIVE_ENV_PREFIXES = exports.SENSITIVE_ENV_VARS = void 0;
44
+ exports.isDaemonChildEnv = isDaemonChildEnv;
44
45
  exports.sanitizeSpawnEnv = sanitizeSpawnEnv;
45
46
  exports.envHasProxy = envHasProxy;
46
47
  exports.withLoopbackNoProxy = withLoopbackNoProxy;
@@ -154,7 +155,40 @@ exports.SENSITIVE_ENV_PREFIX_EXCEPTIONS = new Set([
154
155
  // engine) must keep it to detect they already run as the workload uid. Not
155
156
  // a secret — it authorizes nothing without the matching real uid.
156
157
  'SKRR_WORKLOAD_UID',
158
+ // OSK-13254 — "this process descends from a skrrd agent/tool spawn". It only
159
+ // ever REMOVES authority (a `skrr` that sees it borrows from the daemon and
160
+ // never reads or writes a stored CLI session), so it must survive every later
161
+ // re-sanitization: a Bash tool that runs `skrr code`, whose engine runs `skrr`,
162
+ // is still the agent's process. See `DAEMON_CHILD_ENV` below.
163
+ 'SKRR_DAEMON_CHILD',
157
164
  ]);
165
+ /**
166
+ * OSK-13254 — the marker the daemon stamps on every agent- or tool-driven child
167
+ * (`daemon/src/env-sanitize.ts`, `daemon/src/terminal/agent-terminal-env.ts`).
168
+ *
169
+ * A `skrr` that sees it is a borrower: it redeems short-lived tokens from the
170
+ * daemon's loopback broker, never adopts a CLI refresh session of its own, and
171
+ * never reads the person's stored one (`cli/src/lib/harness-context.ts`). A
172
+ * person's own terminal — including the web terminal, which is a human surface
173
+ * (`humanTerminalEnv`) — does not carry it.
174
+ *
175
+ * The marker can only take authority away, so a process that forges it hurts
176
+ * nobody but itself. On a laptop it is POLICY, not a boundary: a same-uid child
177
+ * that deletes it can do whatever the person's own shell can. Where a uid
178
+ * boundary exists (Dedicated Runtime, identity-split Hosted Machines), the
179
+ * guest descriptor already offers only the access-token mode, so a durable CLI
180
+ * family cannot be minted there whatever the environment says.
181
+ */
182
+ exports.DAEMON_CHILD_ENV = 'SKRR_DAEMON_CHILD';
183
+ /**
184
+ * True when `env` carries the daemon-child marker with ANY non-empty value.
185
+ * Deliberately no "0 means off": the marker only narrows authority, so the
186
+ * one value that could switch it off is the one a request-carried environment
187
+ * would forge.
188
+ */
189
+ function isDaemonChildEnv(env) {
190
+ return Boolean(env[exports.DAEMON_CHILD_ENV]?.trim());
191
+ }
158
192
  /**
159
193
  * Build a sanitized snapshot of the parent's own env for a spawned
160
194
  * child, stripping credentials and library-injection vectors while
@@ -13,8 +13,11 @@
13
13
  * Precedence (high → low):
14
14
  *
15
15
  * 1. flag — `--token <jwt>` CLI flag (debugging)
16
- * 2. env-token — `OVERSKY_TOKEN` env (CI / static; Phase I adds
17
- * server-side scope=ci validation)
16
+ * 2. env-token — `OVERSKY_TOKEN` (CI / static). The CLI also reads
17
+ * `SKRR_TOKEN` via `envTokenNames`; `OVERSKY_TOKEN` wins
18
+ * when both are set, matching the CLI config overlay. A
19
+ * personal access token (`osk_pat_*`) is the credential
20
+ * CI should put here.
18
21
  * 3. auth-helper — `OVERSKY_AUTH_HELPER` script output (rotating
19
22
  * creds — Vault, AWS SM, internal SSO proxy)
20
23
  * 4. fd-handoff — `OVERSKY_AUTH_FD` parent→child IPC (Electron
@@ -64,6 +67,12 @@ export interface CredentialResolverOptions {
64
67
  * string to use that value directly.
65
68
  */
66
69
  envTokenOverride?: string | null;
70
+ /**
71
+ * Environment variables read by the env-token slot, in precedence order.
72
+ * Defaults to `['OVERSKY_TOKEN']`. The CLI passes
73
+ * `['OVERSKY_TOKEN', 'SKRR_TOKEN']` (OSK-13208).
74
+ */
75
+ envTokenNames?: readonly string[];
67
76
  /** Test/explicit override for `OVERSKY_AUTH_HELPER` env. Same semantics. */
68
77
  authHelperPathOverride?: string | null;
69
78
  /**
@@ -143,6 +152,8 @@ export interface AuthHelperSentinelInfo {
143
152
  * (POST /api/daemons/token), MUST NOT schedule refresh,
144
153
  * and on auth failure exits 75 with a CI-specific error
145
154
  * rather than writing needs-reauth.json.
155
+ * - 'pat' — personal access token (`osk_pat_*`, OSK-13208): a static
156
+ * bearer used AS the user by the CLI. Never refreshed.
146
157
  * - 'install' — short-lived web-minted JWT with `scope=daemon-install`.
147
158
  * The daemon exchanges it through the same /api/daemons/token
148
159
  * bootstrap path, persists only the returned daemon
@@ -157,9 +168,17 @@ export interface AuthHelperSentinelInfo {
157
168
  * The kill switch `OVERSKY_DISABLE_CI_TOKEN_RESOLVER=1` forces every token to
158
169
  * `'standard'` for triage purposes.
159
170
  */
160
- export type TokenKind = 'standard' | 'ci' | 'install';
171
+ export type TokenKind = 'standard' | 'ci' | 'install' | 'pat';
161
172
  /** CI-token plaintext prefix; mirrors api/server/services/Auth/daemonCiTokens.js. */
162
173
  export declare const CI_TOKEN_PREFIX = "osk_ci_";
174
+ /** Personal-access-token prefix; mirrors api/server/services/Auth/personalAccessTokens.js. */
175
+ export declare const PERSONAL_ACCESS_TOKEN_PREFIX = "osk_pat_";
176
+ /**
177
+ * True for a kind whose token is static by construction: never refreshed,
178
+ * never rotated into a store. Like `TokenKind` itself this selects a local
179
+ * code path and grants nothing.
180
+ */
181
+ export declare function isStaticTokenKind(kind: TokenKind): boolean;
163
182
  /**
164
183
  * Classify a token by local shape. Pure function; safe to call on any string
165
184
  * (including `null`-coerced empty). Returns `'standard'` for empty input
@@ -13,8 +13,11 @@
13
13
  * Precedence (high → low):
14
14
  *
15
15
  * 1. flag — `--token <jwt>` CLI flag (debugging)
16
- * 2. env-token — `OVERSKY_TOKEN` env (CI / static; Phase I adds
17
- * server-side scope=ci validation)
16
+ * 2. env-token — `OVERSKY_TOKEN` (CI / static). The CLI also reads
17
+ * `SKRR_TOKEN` via `envTokenNames`; `OVERSKY_TOKEN` wins
18
+ * when both are set, matching the CLI config overlay. A
19
+ * personal access token (`osk_pat_*`) is the credential
20
+ * CI should put here.
18
21
  * 3. auth-helper — `OVERSKY_AUTH_HELPER` script output (rotating
19
22
  * creds — Vault, AWS SM, internal SSO proxy)
20
23
  * 4. fd-handoff — `OVERSKY_AUTH_FD` parent→child IPC (Electron
@@ -62,6 +65,16 @@ export const CREDENTIAL_PRECEDENCE = [
62
65
  ];
63
66
  /** CI-token plaintext prefix; mirrors api/server/services/Auth/daemonCiTokens.js. */
64
67
  export const CI_TOKEN_PREFIX = 'osk_ci_';
68
+ /** Personal-access-token prefix; mirrors api/server/services/Auth/personalAccessTokens.js. */
69
+ export const PERSONAL_ACCESS_TOKEN_PREFIX = 'osk_pat_';
70
+ /**
71
+ * True for a kind whose token is static by construction: never refreshed,
72
+ * never rotated into a store. Like `TokenKind` itself this selects a local
73
+ * code path and grants nothing.
74
+ */
75
+ export function isStaticTokenKind(kind) {
76
+ return kind === 'ci' || kind === 'pat';
77
+ }
65
78
  /**
66
79
  * Classify a token by local shape. Pure function; safe to call on any string
67
80
  * (including `null`-coerced empty). Returns `'standard'` for empty input
@@ -97,6 +110,8 @@ export function classifyTokenKind(token) {
97
110
  return 'standard';
98
111
  if (token.startsWith(CI_TOKEN_PREFIX))
99
112
  return 'ci';
113
+ if (token.startsWith(PERSONAL_ACCESS_TOKEN_PREFIX))
114
+ return 'pat';
100
115
  const payload = decodeJwtPayload(token);
101
116
  if (payload &&
102
117
  typeof payload === 'object' &&
@@ -252,8 +267,16 @@ export class CredentialResolver {
252
267
  if (typeof this.opts.envTokenOverride === 'string') {
253
268
  return this.opts.envTokenOverride.length > 0 ? this.opts.envTokenOverride : null;
254
269
  }
255
- const v = process.env.OVERSKY_TOKEN;
256
- return typeof v === 'string' && v.length > 0 ? v : null;
270
+ // `OVERSKY_TOKEN` first (retained by decision, docs/product/skrr-env-inventory.md),
271
+ // then any renamed spelling the caller opted into (`SKRR_TOKEN` for the CLI,
272
+ // OSK-13208). The daemon does not opt in: a CI job that sets `SKRR_TOKEN`
273
+ // for `skrr` must not have a co-located `skrrd` silently adopt it.
274
+ for (const name of this.opts.envTokenNames ?? ['OVERSKY_TOKEN']) {
275
+ const v = process.env[name];
276
+ if (typeof v === 'string' && v.length > 0)
277
+ return v;
278
+ }
279
+ return null;
257
280
  }
258
281
  async tryResolveAuthHelper() {
259
282
  let helperPath;
@@ -38,7 +38,13 @@ export declare function describeDeviceKeySplit(profile: string): {
38
38
  * Order:
39
39
  * 1. Try to load existing keypair from disk.
40
40
  * - Success → state = active.
41
- * - Missing files / corruption / decrypt failure → step 2.
41
+ * - No key material at all (first install) → step 2.
42
+ * - Key material present but unloadable (corruption, decrypt failure,
43
+ * public/private mismatch) → disabled+unreadable_key and a
44
+ * `recovery_required` event, UNLESS `recoverUnreadable` is set. Only
45
+ * an explicit interactive login sets it, because that login proves and
46
+ * re-pins the new key; replacing it on ordinary boot would sign the
47
+ * next refresh with a key the server never pinned.
42
48
  * 2. Generate fresh keypair and persist. Failure to persist is a hard
43
49
  * error landing in disabled+persist_failed.
44
50
  */
@@ -335,7 +335,13 @@ async function consolidateDeviceIdentity(profile) {
335
335
  * Order:
336
336
  * 1. Try to load existing keypair from disk.
337
337
  * - Success → state = active.
338
- * - Missing files / corruption / decrypt failure → step 2.
338
+ * - No key material at all (first install) → step 2.
339
+ * - Key material present but unloadable (corruption, decrypt failure,
340
+ * public/private mismatch) → disabled+unreadable_key and a
341
+ * `recovery_required` event, UNLESS `recoverUnreadable` is set. Only
342
+ * an explicit interactive login sets it, because that login proves and
343
+ * re-pins the new key; replacing it on ordinary boot would sign the
344
+ * next refresh with a key the server never pinned.
339
345
  * 2. Generate fresh keypair and persist. Failure to persist is a hard
340
346
  * error landing in disabled+persist_failed.
341
347
  */
@@ -16,7 +16,7 @@ export { classifyRefreshResponse, type RefreshResponseShape, type ClassifiedRefr
16
16
  export { refreshDaemonToken, revokeDaemonRefreshSession, withAuthLock, persistReauthState, needsReauthState, clearReauthState, installLockExitHandlers, __refreshDiagnostics, __resetUnknown401StreaksForTest, UNKNOWN_401_BUDGET, } from './refresh.js';
17
17
  export { createRefreshScheduler, type RefreshScheduler, type RefreshSchedulerOptions, } from './refreshScheduler.js';
18
18
  export { readAuthFromFd, __setFdReaderForTest, type FdAuthPayload } from './fdToken.js';
19
- export { CredentialResolver, CREDENTIAL_PRECEDENCE, __resetCredentialResolverForTest, invalidateAuthHelperCache, classifyTokenKind, CI_TOKEN_PREFIX, AuthHelperUntrustedError, AuthHelperUnavailableError, type CredentialSource, type CredentialStoreMode, type CredentialResolverOptions, type ResolvedCredential, type TokenKind, type HelperTrustDecision, type AuthHelperBlockedInfo, type AuthHelperSentinelInfo, } from './credentialResolver.js';
19
+ export { CredentialResolver, CREDENTIAL_PRECEDENCE, __resetCredentialResolverForTest, invalidateAuthHelperCache, classifyTokenKind, CI_TOKEN_PREFIX, PERSONAL_ACCESS_TOKEN_PREFIX, isStaticTokenKind, AuthHelperUntrustedError, AuthHelperUnavailableError, type CredentialSource, type CredentialStoreMode, type CredentialResolverOptions, type ResolvedCredential, type TokenKind, type HelperTrustDecision, type AuthHelperBlockedInfo, type AuthHelperSentinelInfo, } from './credentialResolver.js';
20
20
  export { invokeAuthHelper, getDefaultHelperTtlMs, getLastAuthHelperFailureReason, __resetAuthHelperFailureReasonForTest, SENTINEL_TRIGGERING_FAILURES, type HelperResult, type InvokeAuthHelperOptions, type AuthHelperFailureReason, } from './authHelper.js';
21
21
  export { runHeadersHelper, invalidateHeadersHelperCache, type RunHeadersHelperOptions, } from './headers-helper.js';
22
22
  export { generateVerifier, challenge, generateState, safeEqual, verifyChallenge, type PkceChallengeMethod, } from './pkce.js';
@@ -35,7 +35,7 @@ export { ensureMachineDaemonId, legacyDaemonUuids, __resetCachedDaemonIdForTest,
35
35
  export { PAIR_AAD_PREFIX, PAIR_AAD_MAX_LEN, PAIR_BUNDLE_MAX_BASE64_LEN, PAIR_NONCE_LEN, PAIR_PUBKEY_LEN, PAIR_SECRET_LEN, PairBundleError, assemblePairBundleBase64, base64ToUint8Array as pairBase64ToUint8Array, base64UrlToUint8Array as pairBase64UrlToUint8Array, buildPairAad, buildPairUrl, generatePairKeyPair, openPairBundleBase64, parsePairBundle, parsePairPlaintext, parsePairUrl, uint8ArrayToBase64 as pairUint8ArrayToBase64, uint8ArrayToBase64Url as pairUint8ArrayToBase64Url, type AssembleBundleOptions as PairAssembleBundleOptions, type OpenBundleOptions as PairOpenBundleOptions, type PairBundle, type PairBundleErrorCode, type PairKeyPair, type PairPlaintextV1, type PairUrlFields, } from './daemonPair.js';
36
36
  export { HARNESS_TIERS, getHarnessTier, credentialPolicyForTier, tierPermitsConfiguredAutoMode, type HarnessTrustTier, type CredentialDeliveryPolicy, type CredentialMode, } from './harnessTrust.js';
37
37
  export { HARNESSES_LOADING_CLAUDE_SKILLS_LAYOUT, claudeSkillsLayoutEvidence, harnessLoadsClaudeSkillsLayout, } from './harnessSkillLayout.js';
38
- export { sanitizeSpawnEnv, SENSITIVE_ENV_VARS, SENSITIVE_ENV_PREFIXES, SENSITIVE_ENV_SUFFIXES, SENSITIVE_ENV_NAME_TOKENS, SENSITIVE_ENV_PREFIX_EXCEPTIONS, LOOPBACK_NO_PROXY_HOSTS, envHasProxy, withLoopbackNoProxy, } from './spawnEnv.js';
38
+ export { sanitizeSpawnEnv, SENSITIVE_ENV_VARS, SENSITIVE_ENV_PREFIXES, SENSITIVE_ENV_SUFFIXES, SENSITIVE_ENV_NAME_TOKENS, SENSITIVE_ENV_PREFIX_EXCEPTIONS, DAEMON_CHILD_ENV, isDaemonChildEnv, LOOPBACK_NO_PROXY_HOSTS, envHasProxy, withLoopbackNoProxy, } from './spawnEnv.js';
39
39
  export { loopbackFetch, assertLoopbackHttpUrl, isLoopbackHostname, isLoopbackAddress, LoopbackTargetRefusedError, LOOPBACK_DEFAULT_MAX_BODY_BYTES, type LoopbackFetch, type LoopbackFetchInit, } from './loopbackHttp.js';
40
40
  export { CONFIG_DIR_NAME, LEGACY_CONFIG_DIR_NAMES, NATIVE_ID_PREFIX, LEGACY_NATIVE_ID_PREFIXES, DEFAULT_BINARY_NAME, } from './localIdentity.js';
41
41
  export { findLegacyLocalState, describeLegacyState, type LegacyStateFinding, type LegacyStateReport, } from './legacyStatePreflight.js';
@@ -51,7 +51,7 @@ export { CredentialResolver, CREDENTIAL_PRECEDENCE, __resetCredentialResolverFor
51
51
  // H3-6 — public seam 401 handlers call to bust the helper cache so
52
52
  // the next resolve re-invokes OVERSKY_AUTH_HELPER immediately
53
53
  // instead of serving the stale cached token for up to its TTL.
54
- invalidateAuthHelperCache, classifyTokenKind, CI_TOKEN_PREFIX,
54
+ invalidateAuthHelperCache, classifyTokenKind, CI_TOKEN_PREFIX, PERSONAL_ACCESS_TOKEN_PREFIX, isStaticTokenKind,
55
55
  // L6.1 / L6.3 — fail-closed errors thrown by the auth-helper slot.
56
56
  AuthHelperUntrustedError, AuthHelperUnavailableError, } from './credentialResolver.js';
57
57
  // Auth helper — invocation contract for OVERSKY_AUTH_HELPER
@@ -149,7 +149,7 @@ export { HARNESSES_LOADING_CLAUDE_SKILLS_LAYOUT, claudeSkillsLayoutEvidence, har
149
149
  // spawns the SAME engine and did not). `daemon/src/env-sanitize.ts` re-exports
150
150
  // these so its own importers are unchanged, and keeps `filterCustomEnv` — that
151
151
  // governs SERVER-PROVIDED env, which no other process is handed.
152
- export { sanitizeSpawnEnv, SENSITIVE_ENV_VARS, SENSITIVE_ENV_PREFIXES, SENSITIVE_ENV_SUFFIXES, SENSITIVE_ENV_NAME_TOKENS, SENSITIVE_ENV_PREFIX_EXCEPTIONS, LOOPBACK_NO_PROXY_HOSTS, envHasProxy, withLoopbackNoProxy, } from './spawnEnv.js';
152
+ export { sanitizeSpawnEnv, SENSITIVE_ENV_VARS, SENSITIVE_ENV_PREFIXES, SENSITIVE_ENV_SUFFIXES, SENSITIVE_ENV_NAME_TOKENS, SENSITIVE_ENV_PREFIX_EXCEPTIONS, DAEMON_CHILD_ENV, isDaemonChildEnv, LOOPBACK_NO_PROXY_HOSTS, envHasProxy, withLoopbackNoProxy, } from './spawnEnv.js';
153
153
  // OSK-12134 — the one proxy-free client for loopback HTTP. Bun's fetch (and
154
154
  // Node's under NODE_USE_ENV_PROXY) sends 127.0.0.1 requests to HTTP_PROXY,
155
155
  // credentials and all; every loopback caller goes through this instead.
@@ -77,6 +77,31 @@ export declare const SENSITIVE_ENV_SUFFIXES: readonly string[];
77
77
  export declare const SENSITIVE_ENV_NAME_TOKENS: readonly string[];
78
78
  /** Specific names to keep — the prefix sweeps are broad on purpose. */
79
79
  export declare const SENSITIVE_ENV_PREFIX_EXCEPTIONS: ReadonlySet<string>;
80
+ /**
81
+ * OSK-13254 — the marker the daemon stamps on every agent- or tool-driven child
82
+ * (`daemon/src/env-sanitize.ts`, `daemon/src/terminal/agent-terminal-env.ts`).
83
+ *
84
+ * A `skrr` that sees it is a borrower: it redeems short-lived tokens from the
85
+ * daemon's loopback broker, never adopts a CLI refresh session of its own, and
86
+ * never reads the person's stored one (`cli/src/lib/harness-context.ts`). A
87
+ * person's own terminal — including the web terminal, which is a human surface
88
+ * (`humanTerminalEnv`) — does not carry it.
89
+ *
90
+ * The marker can only take authority away, so a process that forges it hurts
91
+ * nobody but itself. On a laptop it is POLICY, not a boundary: a same-uid child
92
+ * that deletes it can do whatever the person's own shell can. Where a uid
93
+ * boundary exists (Dedicated Runtime, identity-split Hosted Machines), the
94
+ * guest descriptor already offers only the access-token mode, so a durable CLI
95
+ * family cannot be minted there whatever the environment says.
96
+ */
97
+ export declare const DAEMON_CHILD_ENV = "SKRR_DAEMON_CHILD";
98
+ /**
99
+ * True when `env` carries the daemon-child marker with ANY non-empty value.
100
+ * Deliberately no "0 means off": the marker only narrows authority, so the
101
+ * one value that could switch it off is the one a request-carried environment
102
+ * would forge.
103
+ */
104
+ export declare function isDaemonChildEnv(env: Readonly<Record<string, string | undefined>>): boolean;
80
105
  /**
81
106
  * Build a sanitized snapshot of the parent's own env for a spawned
82
107
  * child, stripping credentials and library-injection vectors while