@vibe-agent-toolkit/utils 0.1.39-rc.1 → 0.1.39-rc.11

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 (70) hide show
  1. package/dist/fs/file-hash.d.ts +17 -0
  2. package/dist/fs/file-hash.d.ts.map +1 -0
  3. package/dist/fs/file-hash.js +23 -0
  4. package/dist/fs/file-hash.js.map +1 -0
  5. package/dist/git-url.d.ts +43 -0
  6. package/dist/git-url.d.ts.map +1 -0
  7. package/dist/git-url.js +135 -0
  8. package/dist/git-url.js.map +1 -0
  9. package/dist/glob/glob-pattern.d.ts +62 -0
  10. package/dist/glob/glob-pattern.d.ts.map +1 -0
  11. package/dist/glob/glob-pattern.js +115 -0
  12. package/dist/glob/glob-pattern.js.map +1 -0
  13. package/dist/index.d.ts +9 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +12 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/link-auth/build-headers.d.ts +34 -0
  18. package/dist/link-auth/build-headers.d.ts.map +1 -0
  19. package/dist/link-auth/build-headers.js +58 -0
  20. package/dist/link-auth/build-headers.js.map +1 -0
  21. package/dist/link-auth/expand-macro.d.ts +38 -0
  22. package/dist/link-auth/expand-macro.d.ts.map +1 -0
  23. package/dist/link-auth/expand-macro.js +131 -0
  24. package/dist/link-auth/expand-macro.js.map +1 -0
  25. package/dist/link-auth/macros.yaml +50 -0
  26. package/dist/link-auth/resolve-token.d.ts +49 -0
  27. package/dist/link-auth/resolve-token.d.ts.map +1 -0
  28. package/dist/link-auth/resolve-token.js +72 -0
  29. package/dist/link-auth/resolve-token.js.map +1 -0
  30. package/dist/link-auth/resolve.d.ts +58 -0
  31. package/dist/link-auth/resolve.d.ts.map +1 -0
  32. package/dist/link-auth/resolve.js +55 -0
  33. package/dist/link-auth/resolve.js.map +1 -0
  34. package/dist/link-auth/rewrite.d.ts +52 -0
  35. package/dist/link-auth/rewrite.d.ts.map +1 -0
  36. package/dist/link-auth/rewrite.js +102 -0
  37. package/dist/link-auth/rewrite.js.map +1 -0
  38. package/dist/link-auth/select-provider.d.ts +30 -0
  39. package/dist/link-auth/select-provider.d.ts.map +1 -0
  40. package/dist/link-auth/select-provider.js +55 -0
  41. package/dist/link-auth/select-provider.js.map +1 -0
  42. package/dist/link-auth/template.d.ts +40 -0
  43. package/dist/link-auth/template.d.ts.map +1 -0
  44. package/dist/link-auth/template.js +89 -0
  45. package/dist/link-auth/template.js.map +1 -0
  46. package/dist/link-auth/transforms.d.ts +46 -0
  47. package/dist/link-auth/transforms.d.ts.map +1 -0
  48. package/dist/link-auth/transforms.js +52 -0
  49. package/dist/link-auth/transforms.js.map +1 -0
  50. package/dist/path-utils.d.ts +35 -3
  51. package/dist/path-utils.d.ts.map +1 -1
  52. package/dist/path-utils.js +63 -3
  53. package/dist/path-utils.js.map +1 -1
  54. package/dist/skill-test/auth-resolver.d.ts +34 -0
  55. package/dist/skill-test/auth-resolver.d.ts.map +1 -0
  56. package/dist/skill-test/auth-resolver.js +68 -0
  57. package/dist/skill-test/auth-resolver.js.map +1 -0
  58. package/dist/skill-test/env-scrub.d.ts +61 -0
  59. package/dist/skill-test/env-scrub.d.ts.map +1 -0
  60. package/dist/skill-test/env-scrub.js +112 -0
  61. package/dist/skill-test/env-scrub.js.map +1 -0
  62. package/dist/skill-test/index.d.ts +4 -0
  63. package/dist/skill-test/index.d.ts.map +1 -0
  64. package/dist/skill-test/index.js +4 -0
  65. package/dist/skill-test/index.js.map +1 -0
  66. package/dist/skill-test/spawn-claude.d.ts +45 -0
  67. package/dist/skill-test/spawn-claude.d.ts.map +1 -0
  68. package/dist/skill-test/spawn-claude.js +92 -0
  69. package/dist/skill-test/spawn-claude.js.map +1 -0
  70. package/package.json +4 -3
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Provider selection by URL host.
3
+ *
4
+ * Iterates the configured providers in order; the first one whose `match.host`
5
+ * glob matches the URL hostname (and no `match.excludeHost` glob excludes it)
6
+ * claims the URL. Returns `undefined` if no provider claims it — the caller
7
+ * then falls back to anonymous link-checking.
8
+ *
9
+ * Hostname matching is case-insensitive per RFC 3986. Pattern syntax follows
10
+ * `picomatch` (already a utils dep): `*` matches any character, `**` matches
11
+ * across `/`. For hostnames (no slashes) the practical effect is that `*`
12
+ * happily matches dots — e.g. `*.sharepoint.com` claims both
13
+ * `contoso.sharepoint.com` and `foo.bar.sharepoint.com`.
14
+ *
15
+ * Per design issue #113 §4 (vocabulary item 1: match.host + excludeHost).
16
+ */
17
+ import picomatch from 'picomatch';
18
+ /**
19
+ * Find the first provider whose `match` claims the given URL.
20
+ *
21
+ * @returns the matching provider, or `undefined` if none claim the URL (no
22
+ * pattern matched, all candidates were excluded, or the URL is malformed).
23
+ */
24
+ export function selectProvider(url, providers) {
25
+ const host = extractHostname(url);
26
+ if (host === undefined)
27
+ return undefined;
28
+ for (const provider of providers) {
29
+ if (matches(host, provider.match)) {
30
+ return provider;
31
+ }
32
+ }
33
+ return undefined;
34
+ }
35
+ function extractHostname(url) {
36
+ try {
37
+ return new URL(url).hostname;
38
+ }
39
+ catch {
40
+ return undefined;
41
+ }
42
+ }
43
+ function matches(host, match) {
44
+ const lowerHost = host.toLowerCase();
45
+ if (!picomatch.isMatch(lowerHost, match.host.toLowerCase()))
46
+ return false;
47
+ if (match.excludeHost !== undefined) {
48
+ for (const pattern of match.excludeHost) {
49
+ if (picomatch.isMatch(lowerHost, pattern.toLowerCase()))
50
+ return false;
51
+ }
52
+ }
53
+ return true;
54
+ }
55
+ //# sourceMappingURL=select-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-provider.js","sourceRoot":"","sources":["../../src/link-auth/select-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,SAAS,MAAM,WAAW,CAAC;AAOlC;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAC5B,GAAW,EACX,SAAuB;IAEvB,MAAM,IAAI,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAEzC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAClC,OAAO,QAAQ,CAAC;QAClB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;IAClC,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,OAAO,CAAC,IAAY,EAAE,KAAoB;IACjD,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACrC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAAE,OAAO,KAAK,CAAC;IAE1E,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACpC,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YACxC,IAAI,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;gBAAE,OAAO,KAAK,CAAC;QACxE,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Tiny template renderer for linkAuth rewrite + header templates.
3
+ *
4
+ * Syntax (strict, no escapes, no nesting):
5
+ * - `${name}` → context[name]
6
+ * - `${transform(name)}` → applyTransform(transform, context[name])
7
+ *
8
+ * Anything else inside `${...}` throws `TemplateSyntaxError`. Missing context
9
+ * keys throw `TemplateMissingVarError`. Unknown transform names propagate
10
+ * `UnknownTransformError` from the transforms allowlist.
11
+ *
12
+ * This is NOT the project's general-purpose Handlebars renderer
13
+ * (`utils/template.ts`) — that one is `{{...}}` and consumed widely. linkAuth
14
+ * needs different syntax and a closed transform set; the two coexist by
15
+ * namespace (`link-auth/template.ts`).
16
+ */
17
+ /**
18
+ * Thrown when a template references a variable not present in the context.
19
+ * Message names the missing variable and includes the full template for
20
+ * caller-side debugging.
21
+ */
22
+ export declare class TemplateMissingVarError extends Error {
23
+ constructor(varName: string, template: string);
24
+ }
25
+ /**
26
+ * Thrown when a template contains syntactically invalid content inside `${...}`
27
+ * (empty expression, whitespace, unrecognized form) or an unterminated `${`.
28
+ */
29
+ export declare class TemplateSyntaxError extends Error {
30
+ constructor(detail: string, template: string);
31
+ }
32
+ /**
33
+ * Render a template by substituting `${...}` expressions from a context map.
34
+ *
35
+ * @throws {TemplateMissingVarError} if a referenced variable is absent
36
+ * @throws {TemplateSyntaxError} for invalid expressions or unterminated `${`
37
+ * @throws {UnknownTransformError} from a `${transform(name)}` call
38
+ */
39
+ export declare function renderTemplate(template: string, context: Record<string, string>): string;
40
+ //# sourceMappingURL=template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/link-auth/template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAOH;;;;GAIG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAI9C;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAI7C;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAUxF"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Tiny template renderer for linkAuth rewrite + header templates.
3
+ *
4
+ * Syntax (strict, no escapes, no nesting):
5
+ * - `${name}` → context[name]
6
+ * - `${transform(name)}` → applyTransform(transform, context[name])
7
+ *
8
+ * Anything else inside `${...}` throws `TemplateSyntaxError`. Missing context
9
+ * keys throw `TemplateMissingVarError`. Unknown transform names propagate
10
+ * `UnknownTransformError` from the transforms allowlist.
11
+ *
12
+ * This is NOT the project's general-purpose Handlebars renderer
13
+ * (`utils/template.ts`) — that one is `{{...}}` and consumed widely. linkAuth
14
+ * needs different syntax and a closed transform set; the two coexist by
15
+ * namespace (`link-auth/template.ts`).
16
+ */
17
+ import { applyTransform } from './transforms.js';
18
+ const IDENTIFIER = /^[a-zA-Z_]\w*$/;
19
+ const TRANSFORM_CALL = /^(?<fn>[a-zA-Z_]\w*)\((?<arg>[a-zA-Z_]\w*)\)$/;
20
+ /**
21
+ * Thrown when a template references a variable not present in the context.
22
+ * Message names the missing variable and includes the full template for
23
+ * caller-side debugging.
24
+ */
25
+ export class TemplateMissingVarError extends Error {
26
+ constructor(varName, template) {
27
+ super(`Template variable "${varName}" not in context. Template: ${template}`);
28
+ this.name = 'TemplateMissingVarError';
29
+ }
30
+ }
31
+ /**
32
+ * Thrown when a template contains syntactically invalid content inside `${...}`
33
+ * (empty expression, whitespace, unrecognized form) or an unterminated `${`.
34
+ */
35
+ export class TemplateSyntaxError extends Error {
36
+ constructor(detail, template) {
37
+ super(`Invalid template syntax — ${detail}. Template: ${template}`);
38
+ this.name = 'TemplateSyntaxError';
39
+ }
40
+ }
41
+ /**
42
+ * Render a template by substituting `${...}` expressions from a context map.
43
+ *
44
+ * @throws {TemplateMissingVarError} if a referenced variable is absent
45
+ * @throws {TemplateSyntaxError} for invalid expressions or unterminated `${`
46
+ * @throws {UnknownTransformError} from a `${transform(name)}` call
47
+ */
48
+ export function renderTemplate(template, context) {
49
+ const rendered = template.replaceAll(/\$\{([^}]*)\}/g, (_match, body) => resolveExpression(body, template, context));
50
+ if (rendered.includes('${')) {
51
+ throw new TemplateSyntaxError('unterminated "${" with no matching "}"', template);
52
+ }
53
+ return rendered;
54
+ }
55
+ function resolveExpression(body, template, context) {
56
+ if (body !== body.trim()) {
57
+ throw new TemplateSyntaxError(`whitespace in "${body}"`, template);
58
+ }
59
+ if (IDENTIFIER.test(body)) {
60
+ return lookupContextVar(context, body, template);
61
+ }
62
+ const callMatch = TRANSFORM_CALL.exec(body);
63
+ if (callMatch?.groups !== undefined) {
64
+ const { fn, arg } = callMatch.groups;
65
+ if (fn === undefined || arg === undefined) {
66
+ throw new TemplateSyntaxError(`unexpected regex result for "${body}"`, template);
67
+ }
68
+ return applyTransform(fn, lookupContextVar(context, arg, template));
69
+ }
70
+ throw new TemplateSyntaxError(`unrecognized expression "${body}"`, template);
71
+ }
72
+ /**
73
+ * Fetch a variable from the context map, blocking prototype-chain bypass.
74
+ *
75
+ * Without `Object.hasOwn`, `context["__proto__"]` would return `Object.prototype`
76
+ * (a non-undefined object) and the renderer would substitute `[object Object]`
77
+ * into the output. Mirrors the closed-allowlist discipline in `transforms.ts`.
78
+ */
79
+ function lookupContextVar(context, key, template) {
80
+ if (!Object.hasOwn(context, key)) {
81
+ throw new TemplateMissingVarError(key, template);
82
+ }
83
+ const value = context[key];
84
+ if (value === undefined) {
85
+ throw new TemplateMissingVarError(key, template);
86
+ }
87
+ return value;
88
+ }
89
+ //# sourceMappingURL=template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.js","sourceRoot":"","sources":["../../src/link-auth/template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,UAAU,GAAG,gBAAgB,CAAC;AACpC,MAAM,cAAc,GAAG,+CAA+C,CAAC;AAEvE;;;;GAIG;AACH,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAChD,YAAY,OAAe,EAAE,QAAgB;QAC3C,KAAK,CAAC,sBAAsB,OAAO,+BAA+B,QAAQ,EAAE,CAAC,CAAC;QAC9E,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,MAAc,EAAE,QAAgB;QAC1C,KAAK,CAAC,6BAA6B,MAAM,eAAe,QAAQ,EAAE,CAAC,CAAC;QACpE,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,OAA+B;IAC9E,MAAM,QAAQ,GAAG,QAAQ,CAAC,UAAU,CAAC,gBAAgB,EAAE,CAAC,MAAM,EAAE,IAAY,EAAE,EAAE,CAC9E,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAC3C,CAAC;IAEF,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,mBAAmB,CAAC,wCAAwC,EAAE,QAAQ,CAAC,CAAC;IACpF,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,iBAAiB,CACxB,IAAY,EACZ,QAAgB,EAChB,OAA+B;IAE/B,IAAI,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;QACzB,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,IAAI,GAAG,EAAE,QAAQ,CAAC,CAAC;IACrE,CAAC;IAED,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,gBAAgB,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,SAAS,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;QACpC,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC;QACrC,IAAI,EAAE,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC1C,MAAM,IAAI,mBAAmB,CAAC,gCAAgC,IAAI,GAAG,EAAE,QAAQ,CAAC,CAAC;QACnF,CAAC;QACD,OAAO,cAAc,CAAC,EAAE,EAAE,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,MAAM,IAAI,mBAAmB,CAAC,4BAA4B,IAAI,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC/E,CAAC;AAED;;;;;;GAMG;AACH,SAAS,gBAAgB,CACvB,OAA+B,EAC/B,GAAW,EACX,QAAgB;IAEhB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,uBAAuB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACnD,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,uBAAuB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Transform allowlist for linkAuth rewrite templates.
3
+ *
4
+ * Rewrite `to:` templates may call transforms over named regex captures —
5
+ * e.g. `${base64url(u)}` for Microsoft Graph share-ids. The allowed set is
6
+ * frozen in this file: adding a transform requires a VAT PR (see issue #113
7
+ * design §4.1). There is no arbitrary-evaluation path.
8
+ *
9
+ * v1 inputs are assumed to be ASCII URL host/path captures. Non-ASCII edge
10
+ * cases (lone surrogates) are pinned by tests so future regressions surface.
11
+ */
12
+ declare const TRANSFORMS: {
13
+ readonly base64url: (s: string) => string;
14
+ readonly urlencode: (s: string) => string;
15
+ readonly lower: (s: string) => string;
16
+ };
17
+ export type TransformName = keyof typeof TRANSFORMS;
18
+ /**
19
+ * The closed allowlist of transform names. Callers parsing rewrite templates
20
+ * can validate transform calls (e.g. `${base64url(u)}`) against this list at
21
+ * config-load time, surfacing typos before any URL is rewritten.
22
+ */
23
+ export declare const ALLOWED_TRANSFORMS: readonly TransformName[];
24
+ /**
25
+ * Thrown by `applyTransform` when called with a name not in the closed
26
+ * allowlist. The message names the bad transform and the full allowlist so
27
+ * a misconfigured macro surfaces a clear error at load time.
28
+ */
29
+ export declare class UnknownTransformError extends Error {
30
+ constructor(name: string);
31
+ }
32
+ /**
33
+ * Dispatch a transform by name on a string input.
34
+ *
35
+ * Security claim: only the names in `ALLOWED_TRANSFORMS` resolve; any other
36
+ * input throws `UnknownTransformError`. Lookup uses `Object.hasOwn` to block
37
+ * prototype-chain keys (`toString`, `__proto__`, `constructor`, …) that a
38
+ * `name in TRANSFORMS` check would let through.
39
+ *
40
+ * @throws {UnknownTransformError} if `name` is not in the allowlist
41
+ * @throws {URIError} from `urlencode` on lone-surrogate inputs — deliberate;
42
+ * v1 callers pass URL-derived captures that cannot legally contain these
43
+ */
44
+ export declare function applyTransform(name: string, input: string): string;
45
+ export {};
46
+ //# sourceMappingURL=transforms.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transforms.d.ts","sourceRoot":"","sources":["../../src/link-auth/transforms.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,QAAA,MAAM,UAAU;4BACC,MAAM;4BACN,MAAM;wBACV,MAAM;CAC6B,CAAC;AAEjD,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,UAAU,CAAC;AAEpD;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,aAAa,EAEtD,CAAC;AAEF;;;;GAIG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,IAAI,EAAE,MAAM;CAIzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKlE"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Transform allowlist for linkAuth rewrite templates.
3
+ *
4
+ * Rewrite `to:` templates may call transforms over named regex captures —
5
+ * e.g. `${base64url(u)}` for Microsoft Graph share-ids. The allowed set is
6
+ * frozen in this file: adding a transform requires a VAT PR (see issue #113
7
+ * design §4.1). There is no arbitrary-evaluation path.
8
+ *
9
+ * v1 inputs are assumed to be ASCII URL host/path captures. Non-ASCII edge
10
+ * cases (lone surrogates) are pinned by tests so future regressions surface.
11
+ */
12
+ const TRANSFORMS = {
13
+ base64url: (s) => Buffer.from(s, 'utf8').toString('base64url'),
14
+ urlencode: (s) => encodeURIComponent(s),
15
+ lower: (s) => s.toLowerCase(),
16
+ };
17
+ /**
18
+ * The closed allowlist of transform names. Callers parsing rewrite templates
19
+ * can validate transform calls (e.g. `${base64url(u)}`) against this list at
20
+ * config-load time, surfacing typos before any URL is rewritten.
21
+ */
22
+ export const ALLOWED_TRANSFORMS = Object.freeze(Object.keys(TRANSFORMS));
23
+ /**
24
+ * Thrown by `applyTransform` when called with a name not in the closed
25
+ * allowlist. The message names the bad transform and the full allowlist so
26
+ * a misconfigured macro surfaces a clear error at load time.
27
+ */
28
+ export class UnknownTransformError extends Error {
29
+ constructor(name) {
30
+ super(`Unknown transform "${name}". Allowed: ${ALLOWED_TRANSFORMS.join(', ')}.`);
31
+ this.name = 'UnknownTransformError';
32
+ }
33
+ }
34
+ /**
35
+ * Dispatch a transform by name on a string input.
36
+ *
37
+ * Security claim: only the names in `ALLOWED_TRANSFORMS` resolve; any other
38
+ * input throws `UnknownTransformError`. Lookup uses `Object.hasOwn` to block
39
+ * prototype-chain keys (`toString`, `__proto__`, `constructor`, …) that a
40
+ * `name in TRANSFORMS` check would let through.
41
+ *
42
+ * @throws {UnknownTransformError} if `name` is not in the allowlist
43
+ * @throws {URIError} from `urlencode` on lone-surrogate inputs — deliberate;
44
+ * v1 callers pass URL-derived captures that cannot legally contain these
45
+ */
46
+ export function applyTransform(name, input) {
47
+ if (!Object.hasOwn(TRANSFORMS, name)) {
48
+ throw new UnknownTransformError(name);
49
+ }
50
+ return TRANSFORMS[name](input);
51
+ }
52
+ //# sourceMappingURL=transforms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transforms.js","sourceRoot":"","sources":["../../src/link-auth/transforms.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,MAAM,UAAU,GAAG;IACjB,SAAS,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC;IACtE,SAAS,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAC/C,KAAK,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE;CACS,CAAC;AAIjD;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAA6B,MAAM,CAAC,MAAM,CACvE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAoB,CAC3C,CAAC;AAEF;;;;GAIG;AACH,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,IAAY;QACtB,KAAK,CAAC,sBAAsB,IAAI,eAAe,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjF,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,KAAa;IACxD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,UAAU,CAAC,IAAqB,CAAC,CAAC,KAAK,CAAC,CAAC;AAClD,CAAC"}
@@ -175,9 +175,11 @@ export declare function toForwardSlash(p: string): string;
175
175
  * import { safePath } from '@vibe-agent-toolkit/utils';
176
176
  *
177
177
  * // Always forward slashes, even on Windows
178
- * safePath.join('C:\\Users', 'docs', 'file.md') // → 'C:/Users/docs/file.md'
179
- * safePath.resolve('/project', './docs') // → '/project/docs'
180
- * safePath.relative('/project/docs', '/project') // → '..'
178
+ * safePath.join('C:\\Users', 'docs', 'file.md') // → 'C:/Users/docs/file.md'
179
+ * safePath.resolve('/project', './docs') // → '/project/docs'
180
+ * safePath.relative('/project/docs', '/project') // → '..'
181
+ * safePath.joinUnderRoot('/harness', 'skill-abc') // → '/harness/skill-abc'
182
+ * safePath.joinUnderRoot('/harness', '../escape') // throws Error
181
183
  * ```
182
184
  */
183
185
  export declare const safePath: {
@@ -187,6 +189,36 @@ export declare const safePath: {
187
189
  readonly resolve: (...paths: string[]) => string;
188
190
  /** Like `path.relative()` but always returns forward slashes. */
189
191
  readonly relative: (from: string, to: string) => string;
192
+ /**
193
+ * Join path segments under a security root, throwing if the result would escape.
194
+ *
195
+ * Resolves `root + segments` and verifies the result is strictly inside `root`
196
+ * (or equal to it). Throws when any segment would cause the result to escape:
197
+ *
198
+ * - A `..` traversal that climbs above root
199
+ * - An absolute POSIX path segment (e.g. `/etc/passwd`)
200
+ * - A Windows drive-letter segment (e.g. `C:\Users\evil`)
201
+ *
202
+ * On success returns a forward-slash-normalized absolute path (consistent with
203
+ * the other `safePath` helpers).
204
+ *
205
+ * **Use this instead of `safePath.join(root, segment)` whenever `segment` may
206
+ * contain caller-controlled input** — this is the bug class that the original
207
+ * skill-test staging code was vulnerable to on Windows.
208
+ *
209
+ * @returns Forward-slash absolute path guaranteed to be inside `root`.
210
+ * @throws {Error} If the resolved path would escape `root`.
211
+ *
212
+ * @example
213
+ * ```typescript
214
+ * // ✅ Safe — throws if caller passes '../../../etc'
215
+ * const dest = safePath.joinUnderRoot(harnessRoot, stagedDirName(item.name));
216
+ *
217
+ * // ❌ Unsafe — silently escapes on Windows with absolute segment
218
+ * const dest = safePath.join(harnessRoot, item.name);
219
+ * ```
220
+ */
221
+ readonly joinUnderRoot: (root: string, ...segments: string[]) => string;
190
222
  };
191
223
  /**
192
224
  * Resolve an OS-native absolute path from an ESM module's `import.meta.url` and
@@ -1 +1 @@
1
- {"version":3,"file":"path-utils.d.ts","sourceRoot":"","sources":["../src/path-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAgB,MAAM,SAAS,CAAC;AAKlD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,aAAa,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CA+BxD;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAezC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,GACxC,MAAM,CAiBR;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAKjE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAMhE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,QAAQ;IACnB,6DAA6D;8BAC9C,MAAM,EAAE,KAAG,MAAM;IAIhC,gEAAgE;iCAC9C,MAAM,EAAE,KAAG,MAAM;IAInC,iEAAiE;8BAClD,MAAM,MAAM,MAAM,KAAG,MAAM;CAGlC,CAAC;AAEX;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAQ1F;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAGhF"}
1
+ {"version":3,"file":"path-utils.d.ts","sourceRoot":"","sources":["../src/path-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAgB,MAAM,SAAS,CAAC;AAKlD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,aAAa,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CA+BxD;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAezC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,GACxC,MAAM,CAiBR;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAKjE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAMhE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,QAAQ;IACnB,6DAA6D;8BAC9C,MAAM,EAAE,KAAG,MAAM;IAIhC,gEAAgE;iCAC9C,MAAM,EAAE,KAAG,MAAM;IAInC,iEAAiE;8BAClD,MAAM,MAAM,MAAM,KAAG,MAAM;IAI1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;mCACiB,MAAM,eAAe,MAAM,EAAE,KAAG,MAAM;CAuClD,CAAC;AAEX;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAQ1F;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAGhF"}
@@ -260,9 +260,11 @@ export function toForwardSlash(p) {
260
260
  * import { safePath } from '@vibe-agent-toolkit/utils';
261
261
  *
262
262
  * // Always forward slashes, even on Windows
263
- * safePath.join('C:\\Users', 'docs', 'file.md') // → 'C:/Users/docs/file.md'
264
- * safePath.resolve('/project', './docs') // → '/project/docs'
265
- * safePath.relative('/project/docs', '/project') // → '..'
263
+ * safePath.join('C:\\Users', 'docs', 'file.md') // → 'C:/Users/docs/file.md'
264
+ * safePath.resolve('/project', './docs') // → '/project/docs'
265
+ * safePath.relative('/project/docs', '/project') // → '..'
266
+ * safePath.joinUnderRoot('/harness', 'skill-abc') // → '/harness/skill-abc'
267
+ * safePath.joinUnderRoot('/harness', '../escape') // throws Error
266
268
  * ```
267
269
  */
268
270
  export const safePath = {
@@ -278,6 +280,64 @@ export const safePath = {
278
280
  relative(from, to) {
279
281
  return toForwardSlash(path.relative(from, to));
280
282
  },
283
+ /**
284
+ * Join path segments under a security root, throwing if the result would escape.
285
+ *
286
+ * Resolves `root + segments` and verifies the result is strictly inside `root`
287
+ * (or equal to it). Throws when any segment would cause the result to escape:
288
+ *
289
+ * - A `..` traversal that climbs above root
290
+ * - An absolute POSIX path segment (e.g. `/etc/passwd`)
291
+ * - A Windows drive-letter segment (e.g. `C:\Users\evil`)
292
+ *
293
+ * On success returns a forward-slash-normalized absolute path (consistent with
294
+ * the other `safePath` helpers).
295
+ *
296
+ * **Use this instead of `safePath.join(root, segment)` whenever `segment` may
297
+ * contain caller-controlled input** — this is the bug class that the original
298
+ * skill-test staging code was vulnerable to on Windows.
299
+ *
300
+ * @returns Forward-slash absolute path guaranteed to be inside `root`.
301
+ * @throws {Error} If the resolved path would escape `root`.
302
+ *
303
+ * @example
304
+ * ```typescript
305
+ * // ✅ Safe — throws if caller passes '../../../etc'
306
+ * const dest = safePath.joinUnderRoot(harnessRoot, stagedDirName(item.name));
307
+ *
308
+ * // ❌ Unsafe — silently escapes on Windows with absolute segment
309
+ * const dest = safePath.join(harnessRoot, item.name);
310
+ * ```
311
+ */
312
+ joinUnderRoot(root, ...segments) {
313
+ // Eagerly reject any segment that is absolute (POSIX or Windows drive-letter)
314
+ // BEFORE resolving, so the error message can name the offending segment.
315
+ for (const seg of segments) {
316
+ if (path.isAbsolute(seg)) {
317
+ throw new Error(`safePath.joinUnderRoot: segment "${seg}" is absolute and escapes root "${root}".`);
318
+ }
319
+ // Windows drive-letter check for POSIX hosts (path.isAbsolute won't catch
320
+ // 'C:\...' on POSIX, but node's path.win32.isAbsolute does).
321
+ if (path.win32.isAbsolute(seg)) {
322
+ throw new Error(`safePath.joinUnderRoot: segment "${seg}" contains a Windows drive letter and escapes root "${root}".`);
323
+ }
324
+ }
325
+ const resolvedRoot = path.resolve(root);
326
+ const resolvedResult = segments.length > 0
327
+ ? path.resolve(resolvedRoot, ...segments)
328
+ : resolvedRoot;
329
+ // Containment check: normalize both to forward slashes so the comparison
330
+ // is platform-independent and no path.sep is needed in string operations.
331
+ const fwdRoot = toForwardSlash(resolvedRoot);
332
+ const fwdResult = toForwardSlash(resolvedResult);
333
+ // Result must equal root or start with root + '/' (not just startsWith(root)
334
+ // which would match '/rootEvil' when root is '/root').
335
+ const rootPrefix = fwdRoot.endsWith('/') ? fwdRoot : `${fwdRoot}/`;
336
+ if (fwdResult !== fwdRoot && !fwdResult.startsWith(rootPrefix)) {
337
+ throw new Error(`safePath.joinUnderRoot: result "${fwdResult}" escapes root "${fwdRoot}".`);
338
+ }
339
+ return fwdResult;
340
+ },
281
341
  };
282
342
  /**
283
343
  * Resolve an OS-native absolute path from an ESM module's `import.meta.url` and
@@ -1 +1 @@
1
- {"version":3,"file":"path-utils.js","sourceRoot":"","sources":["../src/path-utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"path-utils.js","sourceRoot":"","sources":["../src/path-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ export type AuthMode = 'inherit' | 'subscription' | 'api-key' | 'auto';
2
+ export type AuthMechanism = 'subscription' | 'api-key';
3
+ export interface AuthStatusResult {
4
+ loggedIn: boolean;
5
+ authMethod?: string;
6
+ apiKeySource?: string;
7
+ }
8
+ export type AuthStatusProbe = (env: NodeJS.ProcessEnv) => AuthStatusResult | null;
9
+ export interface ResolveAuthOptions {
10
+ mode: AuthMode;
11
+ requireAuth?: AuthMechanism;
12
+ sourceEnv: NodeJS.ProcessEnv;
13
+ /** Injected in tests; defaults to the real CLI probe in production. */
14
+ probe?: AuthStatusProbe;
15
+ modelVars?: string[];
16
+ }
17
+ export interface ResolvedAuth {
18
+ forwardedEnv: NodeJS.ProcessEnv;
19
+ effectiveMechanism: AuthMechanism;
20
+ authMethod?: string;
21
+ apiKeySource?: string;
22
+ }
23
+ /** A preflight auth failure — maps to exit code 2. */
24
+ export declare class AuthPreflightError extends Error {
25
+ readonly exitCode: 2;
26
+ constructor(message: string);
27
+ }
28
+ /**
29
+ * Token-free auth probe (spec §8/§10). Runs `claude auth status --json` in the
30
+ * given env: returns in ~150ms, exit 0, spends NO tokens. NOT a `-p` call.
31
+ */
32
+ export declare function probeAuthStatus(env: NodeJS.ProcessEnv): AuthStatusResult | null;
33
+ export declare function resolveAuth(opts: ResolveAuthOptions): ResolvedAuth;
34
+ //# sourceMappingURL=auth-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-resolver.d.ts","sourceRoot":"","sources":["../../src/skill-test/auth-resolver.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,cAAc,GAAG,SAAS,GAAG,MAAM,CAAC;AACvE,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,SAAS,CAAC;AAEvD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,KAAK,gBAAgB,GAAG,IAAI,CAAC;AAElF,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,QAAQ,CAAC;IACf,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC,UAAU,CAAC;IAC7B,uEAAuE;IACvE,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC,UAAU,CAAC;IAChC,kBAAkB,EAAE,aAAa,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,sDAAsD;AACtD,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,QAAQ,EAAG,CAAC,CAAU;gBACnB,OAAO,EAAE,MAAM;CAI5B;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,gBAAgB,GAAG,IAAI,CAa/E;AAgBD,wBAAgB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,YAAY,CA+BlE"}
@@ -0,0 +1,68 @@
1
+ import { safeExecResult } from '../safe-exec.js';
2
+ import { buildForwardedEnv } from './env-scrub.js';
3
+ /** A preflight auth failure — maps to exit code 2. */
4
+ export class AuthPreflightError extends Error {
5
+ exitCode = 2;
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = 'AuthPreflightError';
9
+ }
10
+ }
11
+ /**
12
+ * Token-free auth probe (spec §8/§10). Runs `claude auth status --json` in the
13
+ * given env: returns in ~150ms, exit 0, spends NO tokens. NOT a `-p` call.
14
+ */
15
+ export function probeAuthStatus(env) {
16
+ const res = safeExecResult('claude', ['auth', 'status', '--json'], { env, encoding: 'utf8', stdio: 'pipe' });
17
+ if (!res.success)
18
+ return null;
19
+ try {
20
+ const parsed = JSON.parse(res.stdout.toString());
21
+ return {
22
+ loggedIn: parsed['loggedIn'] === true,
23
+ ...(typeof parsed['authMethod'] === 'string' ? { authMethod: parsed['authMethod'] } : {}),
24
+ ...(typeof parsed['apiKeySource'] === 'string' ? { apiKeySource: parsed['apiKeySource'] } : {}),
25
+ };
26
+ }
27
+ catch {
28
+ return null;
29
+ }
30
+ }
31
+ function hasInferenceKey(env) {
32
+ return Boolean(env['ANTHROPIC_API_KEY'] ?? env['ANTHROPIC_AUTH_TOKEN']);
33
+ }
34
+ /** Decide whether to scrub the inference key, given mode + a subscription-present probe. */
35
+ function decideScrub(mode, sourceEnv, probe) {
36
+ if (mode === 'subscription')
37
+ return true;
38
+ if (mode === 'api-key' || mode === 'auto')
39
+ return false;
40
+ // inherit: scrub the key only if a subscription is actually logged in.
41
+ const scrubbed = buildForwardedEnv(sourceEnv, { scrubInferenceKey: true });
42
+ const status = probe(scrubbed);
43
+ return status?.loggedIn === true;
44
+ }
45
+ export function resolveAuth(opts) {
46
+ const probe = opts.probe ?? probeAuthStatus;
47
+ const baseOpts = opts.modelVars ? { modelVars: opts.modelVars } : {};
48
+ if (opts.mode === 'api-key' && !hasInferenceKey(opts.sourceEnv)) {
49
+ throw new AuthPreflightError('--auth api-key requires ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN to be set.');
50
+ }
51
+ const scrubInferenceKey = decideScrub(opts.mode, opts.sourceEnv, probe);
52
+ const forwardedEnv = buildForwardedEnv(opts.sourceEnv, { scrubInferenceKey, ...baseOpts });
53
+ const status = probe(forwardedEnv);
54
+ if (opts.mode === 'subscription' && status?.loggedIn !== true) {
55
+ throw new AuthPreflightError('--auth subscription requires a logged-in subscription (claude auth status reports not logged in).');
56
+ }
57
+ const effectiveMechanism = !scrubInferenceKey && hasInferenceKey(forwardedEnv) ? 'api-key' : 'subscription';
58
+ if (opts.requireAuth && opts.requireAuth !== effectiveMechanism) {
59
+ throw new AuthPreflightError(`--require-auth ${opts.requireAuth} but the effective mechanism is ${effectiveMechanism}. Refusing to spend tokens.`);
60
+ }
61
+ return {
62
+ forwardedEnv,
63
+ effectiveMechanism,
64
+ ...(status?.authMethod ? { authMethod: status.authMethod } : {}),
65
+ ...(status?.apiKeySource ? { apiKeySource: status.apiKeySource } : {}),
66
+ };
67
+ }
68
+ //# sourceMappingURL=auth-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-resolver.js","sourceRoot":"","sources":["../../src/skill-test/auth-resolver.ts"],"names":[],"mappings":"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"}