@keynv/core 0.1.0-rc.23

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 (78) hide show
  1. package/LICENSE +21 -0
  2. package/dist/audit/chain.d.ts +44 -0
  3. package/dist/audit/chain.d.ts.map +1 -0
  4. package/dist/audit/chain.js +134 -0
  5. package/dist/audit/chain.js.map +1 -0
  6. package/dist/audit/chain.test.d.ts +2 -0
  7. package/dist/audit/chain.test.d.ts.map +1 -0
  8. package/dist/audit/chain.test.js +192 -0
  9. package/dist/audit/chain.test.js.map +1 -0
  10. package/dist/audit/index.d.ts +5 -0
  11. package/dist/audit/index.d.ts.map +1 -0
  12. package/dist/audit/index.js +4 -0
  13. package/dist/audit/index.js.map +1 -0
  14. package/dist/audit/payload-schemas.d.ts +343 -0
  15. package/dist/audit/payload-schemas.d.ts.map +1 -0
  16. package/dist/audit/payload-schemas.js +112 -0
  17. package/dist/audit/payload-schemas.js.map +1 -0
  18. package/dist/audit/payload-schemas.test.d.ts +2 -0
  19. package/dist/audit/payload-schemas.test.d.ts.map +1 -0
  20. package/dist/audit/payload-schemas.test.js +93 -0
  21. package/dist/audit/payload-schemas.test.js.map +1 -0
  22. package/dist/audit/types.d.ts +34 -0
  23. package/dist/audit/types.d.ts.map +1 -0
  24. package/dist/audit/types.js +6 -0
  25. package/dist/audit/types.js.map +1 -0
  26. package/dist/crypto/envelope.d.ts +55 -0
  27. package/dist/crypto/envelope.d.ts.map +1 -0
  28. package/dist/crypto/envelope.js +108 -0
  29. package/dist/crypto/envelope.js.map +1 -0
  30. package/dist/crypto/envelope.test.d.ts +2 -0
  31. package/dist/crypto/envelope.test.d.ts.map +1 -0
  32. package/dist/crypto/envelope.test.js +163 -0
  33. package/dist/crypto/envelope.test.js.map +1 -0
  34. package/dist/crypto/index.d.ts +5 -0
  35. package/dist/crypto/index.d.ts.map +1 -0
  36. package/dist/crypto/index.js +4 -0
  37. package/dist/crypto/index.js.map +1 -0
  38. package/dist/crypto/sodium.d.ts +21 -0
  39. package/dist/crypto/sodium.d.ts.map +1 -0
  40. package/dist/crypto/sodium.js +43 -0
  41. package/dist/crypto/sodium.js.map +1 -0
  42. package/dist/crypto/types.d.ts +37 -0
  43. package/dist/crypto/types.d.ts.map +1 -0
  44. package/dist/crypto/types.js +11 -0
  45. package/dist/crypto/types.js.map +1 -0
  46. package/dist/index.d.ts +5 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +5 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/reference/index.d.ts +4 -0
  51. package/dist/reference/index.d.ts.map +1 -0
  52. package/dist/reference/index.js +3 -0
  53. package/dist/reference/index.js.map +1 -0
  54. package/dist/reference/parser-property.test.d.ts +2 -0
  55. package/dist/reference/parser-property.test.d.ts.map +1 -0
  56. package/dist/reference/parser-property.test.js +115 -0
  57. package/dist/reference/parser-property.test.js.map +1 -0
  58. package/dist/reference/parser.d.ts +54 -0
  59. package/dist/reference/parser.d.ts.map +1 -0
  60. package/dist/reference/parser.js +144 -0
  61. package/dist/reference/parser.js.map +1 -0
  62. package/dist/reference/parser.test.d.ts +2 -0
  63. package/dist/reference/parser.test.d.ts.map +1 -0
  64. package/dist/reference/parser.test.js +195 -0
  65. package/dist/reference/parser.test.js.map +1 -0
  66. package/dist/reference/types.d.ts +52 -0
  67. package/dist/reference/types.d.ts.map +1 -0
  68. package/dist/reference/types.js +11 -0
  69. package/dist/reference/types.js.map +1 -0
  70. package/dist/validation/index.d.ts +33 -0
  71. package/dist/validation/index.d.ts.map +1 -0
  72. package/dist/validation/index.js +45 -0
  73. package/dist/validation/index.js.map +1 -0
  74. package/dist/validation/schemas.test.d.ts +2 -0
  75. package/dist/validation/schemas.test.d.ts.map +1 -0
  76. package/dist/validation/schemas.test.js +18 -0
  77. package/dist/validation/schemas.test.js.map +1 -0
  78. package/package.json +48 -0
@@ -0,0 +1,115 @@
1
+ import fc from 'fast-check';
2
+ import { describe, expect, it } from 'vitest';
3
+ import { buildAlias, findAliases, parseAlias } from './parser.js';
4
+ const projectArb = fc
5
+ .stringMatching(/^[a-z0-9][a-z0-9-]{0,47}$/)
6
+ .filter((s) => s.length >= 1 && s.length <= 48);
7
+ const envArb = fc
8
+ .stringMatching(/^[a-z0-9][a-z0-9-]{0,23}$/)
9
+ .filter((s) => s.length >= 1 && s.length <= 24);
10
+ const keyArb = fc
11
+ .stringMatching(/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/)
12
+ .filter((s) => s.length >= 1 && s.length <= 64);
13
+ const aliasPartsArb = fc.record({
14
+ project: projectArb,
15
+ environment: envArb,
16
+ key: keyArb,
17
+ });
18
+ describe('parseAlias — properties', () => {
19
+ it('round-trips: build → parse yields the same components', () => {
20
+ fc.assert(fc.property(aliasPartsArb, (parts) => {
21
+ const built = buildAlias(parts);
22
+ expect(built).not.toBeNull();
23
+ if (!built)
24
+ return;
25
+ const reparsed = parseAlias(built.literal);
26
+ expect(reparsed).toEqual(built);
27
+ }), { numRuns: 500 });
28
+ });
29
+ it('is idempotent: parseAlias(parseAlias(x).literal) equals parseAlias(x)', () => {
30
+ fc.assert(fc.property(aliasPartsArb, (parts) => {
31
+ const first = parseAlias(`@${parts.project}.${parts.environment}.${parts.key}`);
32
+ if (!first)
33
+ return;
34
+ const second = parseAlias(first.literal);
35
+ expect(second).toEqual(first);
36
+ }), { numRuns: 500 });
37
+ });
38
+ it('never accepts a string with whitespace', () => {
39
+ fc.assert(fc.property(aliasPartsArb, fc.constantFrom(' ', '\t', '\n', '\r'), fc.integer({ min: 0, max: 80 }), (parts, ws, position) => {
40
+ const literal = `@${parts.project}.${parts.environment}.${parts.key}`;
41
+ if (position >= literal.length)
42
+ return;
43
+ const tampered = literal.slice(0, position) + ws + literal.slice(position);
44
+ expect(parseAlias(tampered)).toBeNull();
45
+ }), { numRuns: 500 });
46
+ });
47
+ it('never accepts non-string inputs', () => {
48
+ fc.assert(fc.property(fc.oneof(fc.constant(undefined), fc.constant(null), fc.integer(), fc.boolean(), fc.array(fc.string()), fc.object()), (notString) => {
49
+ expect(parseAlias(notString)).toBeNull();
50
+ }), { numRuns: 200 });
51
+ });
52
+ });
53
+ describe('findAliases — properties', () => {
54
+ it('every match parses back to itself', () => {
55
+ fc.assert(fc.property(fc.string({ maxLength: 200 }), (text) => {
56
+ for (const m of findAliases(text)) {
57
+ const reparsed = parseAlias(m.literal);
58
+ expect(reparsed).not.toBeNull();
59
+ expect(reparsed?.project).toBe(m.project);
60
+ expect(reparsed?.environment).toBe(m.environment);
61
+ expect(reparsed?.key).toBe(m.key);
62
+ }
63
+ }), { numRuns: 500 });
64
+ });
65
+ it('match offsets reproduce the literal exactly', () => {
66
+ fc.assert(fc.property(fc.string({ maxLength: 200 }), (text) => {
67
+ for (const m of findAliases(text)) {
68
+ expect(text.slice(m.start, m.end)).toBe(m.literal);
69
+ }
70
+ }), { numRuns: 500 });
71
+ });
72
+ it('matches do not overlap and are sorted', () => {
73
+ fc.assert(fc.property(fc.string({ maxLength: 400 }), (text) => {
74
+ const matches = findAliases(text);
75
+ for (let i = 1; i < matches.length; i++) {
76
+ const cur = matches[i];
77
+ const prev = matches[i - 1];
78
+ if (!cur || !prev)
79
+ continue;
80
+ expect(cur.start).toBeGreaterThanOrEqual(prev.end);
81
+ }
82
+ }), { numRuns: 500 });
83
+ });
84
+ it('embedding a built alias inside neutral context produces exactly one match', () => {
85
+ fc.assert(fc.property(aliasPartsArb, fc.constantFrom('use ', 'see (', '"', "'", ' '), fc.constantFrom(' here', ')', '"', "'", '!', '.'), (parts, prefix, suffix) => {
86
+ const built = buildAlias(parts);
87
+ if (!built)
88
+ return;
89
+ const text = `${prefix}${built.literal}${suffix}`;
90
+ const matches = findAliases(text);
91
+ expect(matches).toHaveLength(1);
92
+ expect(matches[0]?.literal).toBe(built.literal);
93
+ }), { numRuns: 300 });
94
+ });
95
+ });
96
+ describe('findAliases — performance budget', () => {
97
+ it('handles a 10K-line text in under 250ms', () => {
98
+ const lines = [];
99
+ for (let i = 0; i < 10_000; i++) {
100
+ const project = `proj${i % 1000}`;
101
+ const env = i % 2 === 0 ? 'dev' : 'prod';
102
+ const key = `key_${i}`;
103
+ lines.push(i % 5 === 0
104
+ ? `lorem ipsum @${project}.${env}.${key} dolor sit`
105
+ : 'lorem ipsum dolor sit amet consectetur');
106
+ }
107
+ const text = lines.join('\n');
108
+ const start = performance.now();
109
+ const matches = findAliases(text);
110
+ const elapsed = performance.now() - start;
111
+ expect(matches.length).toBeGreaterThan(0);
112
+ expect(elapsed).toBeLessThan(250);
113
+ });
114
+ });
115
+ //# sourceMappingURL=parser-property.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser-property.test.js","sourceRoot":"","sources":["../../src/reference/parser-property.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import type { Alias, AliasMatch, FindMode } from './types.js';
2
+ /**
3
+ * Parses an exact alias literal. Returns `null` if `input` is not a
4
+ * well-formed `@project.environment.key` reference.
5
+ *
6
+ * Strict: case-sensitive (lowercase only), exactly three components,
7
+ * each within the documented length limits.
8
+ */
9
+ export declare function parseAlias(input: string): Alias | null;
10
+ /**
11
+ * Scans a string for embedded aliases.
12
+ *
13
+ * The default `text` mode is conservative and avoids common false positives
14
+ * like email addresses. Use `argv` mode when scanning shell command arguments
15
+ * where patterns such as `mysql -p@billing.prod.db_password` are expected.
16
+ *
17
+ * Returned matches are ordered by `start` ascending and never overlap.
18
+ */
19
+ export declare function findAliases(text: string, opts?: {
20
+ mode?: FindMode;
21
+ }): AliasMatch[];
22
+ /**
23
+ * Walks an argv array and returns every alias found inside any element.
24
+ *
25
+ * Uses `argv` mode automatically. The returned offsets are relative to the
26
+ * containing argv string.
27
+ */
28
+ export declare function findAliasesInArgv(argv: readonly string[]): Array<{
29
+ argvIndex: number;
30
+ matches: AliasMatch[];
31
+ }>;
32
+ /**
33
+ * Replaces every alias found in `text` with the value returned by `resolve`.
34
+ *
35
+ * Replacement is right-to-left so that already-computed offsets remain
36
+ * valid. The resolver receives the parsed alias and returns the string that
37
+ * should appear in its place. Throwing inside the resolver propagates.
38
+ */
39
+ export declare function replaceAliases(text: string, resolve: (alias: Alias) => string, opts?: {
40
+ mode?: FindMode;
41
+ }): string;
42
+ /**
43
+ * Builds an alias literal from validated components without parsing.
44
+ * Returns `null` if any component would fail validation.
45
+ *
46
+ * Useful for building aliases from server data (where components come from
47
+ * separate columns) without re-running the full parser.
48
+ */
49
+ export declare function buildAlias(parts: {
50
+ project: string;
51
+ environment: string;
52
+ key: string;
53
+ }): Alias | null;
54
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/reference/parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAgB9D;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAmBtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,QAAQ,CAAA;CAAO,GAAG,UAAU,EAAE,CAmBtF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,KAAK,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,UAAU,EAAE,CAAA;CAAE,CAAC,CAWrD;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,EACjC,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,QAAQ,CAAA;CAAO,GAC7B,MAAM,CAsBR;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;CACb,GAAG,KAAK,GAAG,IAAI,CAUf"}
@@ -0,0 +1,144 @@
1
+ const PROJECT_RE = /^[a-z0-9][a-z0-9-]{0,47}$/;
2
+ const ENV_RE = /^[a-z0-9][a-z0-9-]{0,23}$/;
3
+ const KEY_RE = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/;
4
+ // Trailing boundary: forbid an immediately-following word char (would extend
5
+ // the key) AND forbid a `.<alias-start>` (would imply a 4-part alias). A bare
6
+ // trailing `.` — sentence punctuation — is allowed.
7
+ const TRAILING_BOUNDARY = '(?!\\w|\\.[a-z0-9])';
8
+ const TEXT_FIND_SOURCE = `(?<![\\w.@/])@[a-z0-9][a-z0-9-]{0,47}\\.[a-z0-9][a-z0-9-]{0,23}\\.[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}${TRAILING_BOUNDARY}`;
9
+ const ARGV_FIND_SOURCE = `@[a-z0-9][a-z0-9-]{0,47}\\.[a-z0-9][a-z0-9-]{0,23}\\.[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}${TRAILING_BOUNDARY}`;
10
+ const TEXT_FIND_RE = new RegExp(TEXT_FIND_SOURCE, 'g');
11
+ const ARGV_FIND_RE = new RegExp(ARGV_FIND_SOURCE, 'g');
12
+ /**
13
+ * Parses an exact alias literal. Returns `null` if `input` is not a
14
+ * well-formed `@project.environment.key` reference.
15
+ *
16
+ * Strict: case-sensitive (lowercase only), exactly three components,
17
+ * each within the documented length limits.
18
+ */
19
+ export function parseAlias(input) {
20
+ if (typeof input !== 'string' || input.length < 6)
21
+ return null;
22
+ if (input.charCodeAt(0) !== 64)
23
+ return null;
24
+ const dot1 = input.indexOf('.', 1);
25
+ if (dot1 < 2)
26
+ return null;
27
+ const dot2 = input.indexOf('.', dot1 + 1);
28
+ if (dot2 < 0 || dot2 === dot1 + 1)
29
+ return null;
30
+ if (input.indexOf('.', dot2 + 1) !== -1)
31
+ return null;
32
+ const project = input.slice(1, dot1);
33
+ const environment = input.slice(dot1 + 1, dot2);
34
+ const key = input.slice(dot2 + 1);
35
+ if (!PROJECT_RE.test(project))
36
+ return null;
37
+ if (!ENV_RE.test(environment))
38
+ return null;
39
+ if (!KEY_RE.test(key))
40
+ return null;
41
+ return { literal: input, project, environment, key };
42
+ }
43
+ /**
44
+ * Scans a string for embedded aliases.
45
+ *
46
+ * The default `text` mode is conservative and avoids common false positives
47
+ * like email addresses. Use `argv` mode when scanning shell command arguments
48
+ * where patterns such as `mysql -p@billing.prod.db_password` are expected.
49
+ *
50
+ * Returned matches are ordered by `start` ascending and never overlap.
51
+ */
52
+ export function findAliases(text, opts = {}) {
53
+ if (typeof text !== 'string' || text.length === 0)
54
+ return [];
55
+ const re = opts.mode === 'argv' ? ARGV_FIND_RE : TEXT_FIND_RE;
56
+ re.lastIndex = 0;
57
+ const matches = [];
58
+ for (const m of text.matchAll(re)) {
59
+ const literal = m[0];
60
+ const start = m.index;
61
+ if (start === undefined)
62
+ continue;
63
+ const parsed = parseAlias(literal);
64
+ if (!parsed)
65
+ continue;
66
+ matches.push({
67
+ ...parsed,
68
+ start,
69
+ end: start + literal.length,
70
+ });
71
+ }
72
+ return matches;
73
+ }
74
+ /**
75
+ * Walks an argv array and returns every alias found inside any element.
76
+ *
77
+ * Uses `argv` mode automatically. The returned offsets are relative to the
78
+ * containing argv string.
79
+ */
80
+ export function findAliasesInArgv(argv) {
81
+ const result = [];
82
+ for (let i = 0; i < argv.length; i++) {
83
+ const element = argv[i];
84
+ if (typeof element !== 'string')
85
+ continue;
86
+ const matches = findAliases(element, { mode: 'argv' });
87
+ if (matches.length > 0) {
88
+ result.push({ argvIndex: i, matches });
89
+ }
90
+ }
91
+ return result;
92
+ }
93
+ /**
94
+ * Replaces every alias found in `text` with the value returned by `resolve`.
95
+ *
96
+ * Replacement is right-to-left so that already-computed offsets remain
97
+ * valid. The resolver receives the parsed alias and returns the string that
98
+ * should appear in its place. Throwing inside the resolver propagates.
99
+ */
100
+ export function replaceAliases(text, resolve, opts = {}) {
101
+ if (typeof text !== 'string' || text.length === 0)
102
+ return text;
103
+ const matches = findAliases(text, opts);
104
+ if (matches.length === 0)
105
+ return text;
106
+ let out = text;
107
+ for (let i = matches.length - 1; i >= 0; i--) {
108
+ const m = matches[i];
109
+ if (!m)
110
+ continue;
111
+ const replacement = resolve(m);
112
+ // Circularity guard: only reject a replacement that is itself a FULLY
113
+ // VALID alias literal (`@project.env.key`). A value that merely starts
114
+ // with `@` plus a kebab segment — e.g. a real secret like `@my-token`
115
+ // or `@2fa-backup` — is not an alias and must pass through unchanged.
116
+ if (parseAlias(replacement) !== null) {
117
+ throw new Error(`replaceAliases: resolved value for ${m.literal} is itself a valid alias (${replacement}). Circular or misconfigured resolution detected.`);
118
+ }
119
+ out = out.slice(0, m.start) + replacement + out.slice(m.end);
120
+ }
121
+ return out;
122
+ }
123
+ /**
124
+ * Builds an alias literal from validated components without parsing.
125
+ * Returns `null` if any component would fail validation.
126
+ *
127
+ * Useful for building aliases from server data (where components come from
128
+ * separate columns) without re-running the full parser.
129
+ */
130
+ export function buildAlias(parts) {
131
+ if (!PROJECT_RE.test(parts.project))
132
+ return null;
133
+ if (!ENV_RE.test(parts.environment))
134
+ return null;
135
+ if (!KEY_RE.test(parts.key))
136
+ return null;
137
+ return {
138
+ literal: `@${parts.project}.${parts.environment}.${parts.key}`,
139
+ project: parts.project,
140
+ environment: parts.environment,
141
+ key: parts.key,
142
+ };
143
+ }
144
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/reference/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parser.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.test.d.ts","sourceRoot":"","sources":["../../src/reference/parser.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,195 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { buildAlias, findAliases, findAliasesInArgv, parseAlias, replaceAliases, } from './parser.js';
3
+ describe('parseAlias — happy paths', () => {
4
+ it('parses a canonical alias', () => {
5
+ expect(parseAlias('@billing.prod.db_password')).toEqual({
6
+ literal: '@billing.prod.db_password',
7
+ project: 'billing',
8
+ environment: 'prod',
9
+ key: 'db_password',
10
+ });
11
+ });
12
+ it('parses kebab-case and snake_case keys together', () => {
13
+ expect(parseAlias('@auth-service.staging.jwt-signing-key')).toEqual({
14
+ literal: '@auth-service.staging.jwt-signing-key',
15
+ project: 'auth-service',
16
+ environment: 'staging',
17
+ key: 'jwt-signing-key',
18
+ });
19
+ });
20
+ it('parses uppercase keys (standard .env convention)', () => {
21
+ expect(parseAlias('@billing.prod.DATABASE_URL')).toEqual({
22
+ literal: '@billing.prod.DATABASE_URL',
23
+ project: 'billing',
24
+ environment: 'prod',
25
+ key: 'DATABASE_URL',
26
+ });
27
+ expect(parseAlias('@auth-service.staging.API_KEY')).toMatchObject({
28
+ key: 'API_KEY',
29
+ });
30
+ expect(parseAlias('@billing.prod.Secret_Token_1')).toMatchObject({
31
+ key: 'Secret_Token_1',
32
+ });
33
+ });
34
+ it('parses numeric components', () => {
35
+ expect(parseAlias('@p1.pr-1234.k_42')).toMatchObject({
36
+ project: 'p1',
37
+ environment: 'pr-1234',
38
+ key: 'k_42',
39
+ });
40
+ });
41
+ it('accepts max-length components', () => {
42
+ const project = `a${'b'.repeat(47)}`;
43
+ const environment = `a${'b'.repeat(23)}`;
44
+ const key = `a${'b'.repeat(63)}`;
45
+ const literal = `@${project}.${environment}.${key}`;
46
+ expect(parseAlias(literal)).toEqual({ literal, project, environment, key });
47
+ });
48
+ });
49
+ describe('parseAlias — rejections', () => {
50
+ it.each([
51
+ ['no @ prefix', 'billing.prod.db_password'],
52
+ ['empty', ''],
53
+ ['just @', '@'],
54
+ ['too short', '@a.b'],
55
+ ['only two parts', '@billing.prod'],
56
+ ['four parts', '@billing.prod.db.password'],
57
+ ['empty project', '@.prod.key'],
58
+ ['empty env', '@billing..key'],
59
+ ['empty key', '@billing.prod.'],
60
+ ['uppercase project', '@Billing.prod.key'],
61
+ ['uppercase env', '@billing.Prod.key'],
62
+ ['underscore in project (project allows kebab only)', '@bil_ling.prod.key'],
63
+ ['leading dash in project', '@-billing.prod.key'],
64
+ ['leading dash in env', '@billing.-prod.key'],
65
+ ['leading dash in key', '@billing.prod.-key'],
66
+ ['trailing newline', '@billing.prod.key\n'],
67
+ ['internal whitespace', '@billing. prod.key'],
68
+ ['too long project (49)', `@${'a'.repeat(49)}.prod.key`],
69
+ ['too long env (25)', `@billing.${'a'.repeat(25)}.key`],
70
+ ['too long key (65)', `@billing.prod.${'a'.repeat(65)}`],
71
+ ['extra @', '@@billing.prod.key'],
72
+ ['unicode', '@billing.prod.şifre'],
73
+ ])('rejects %s: %s', (_label, input) => {
74
+ expect(parseAlias(input)).toBeNull();
75
+ });
76
+ it('rejects non-string input', () => {
77
+ expect(parseAlias(undefined)).toBeNull();
78
+ expect(parseAlias(null)).toBeNull();
79
+ expect(parseAlias(42)).toBeNull();
80
+ });
81
+ });
82
+ describe('findAliases — text mode (conservative)', () => {
83
+ it('finds an alias inside a sentence', () => {
84
+ const text = 'Use @billing.prod.db_password before the migration.';
85
+ const matches = findAliases(text);
86
+ expect(matches).toHaveLength(1);
87
+ expect(matches[0]?.literal).toBe('@billing.prod.db_password');
88
+ expect(text.slice(matches[0]?.start, matches[0]?.end)).toBe('@billing.prod.db_password');
89
+ });
90
+ it('finds an alias inside double quotes', () => {
91
+ const text = 'connect to "@billing.prod.db_url" please';
92
+ expect(findAliases(text).map((m) => m.literal)).toEqual(['@billing.prod.db_url']);
93
+ });
94
+ it('finds an alias inside single quotes', () => {
95
+ const text = "connect to '@billing.prod.db_url'";
96
+ expect(findAliases(text).map((m) => m.literal)).toEqual(['@billing.prod.db_url']);
97
+ });
98
+ it('handles trailing punctuation', () => {
99
+ const text = 'aliases: (@billing.prod.db_password), end.';
100
+ expect(findAliases(text).map((m) => m.literal)).toEqual(['@billing.prod.db_password']);
101
+ });
102
+ it('finds multiple aliases on one line', () => {
103
+ const text = 'Two: @a.b.c and @x-1.y.z42 work.';
104
+ expect(findAliases(text).map((m) => m.literal)).toEqual(['@a.b.c', '@x-1.y.z42']);
105
+ });
106
+ it('does NOT match inside an email address', () => {
107
+ const text = 'contact support@billing.example.com for help';
108
+ expect(findAliases(text)).toEqual([]);
109
+ });
110
+ it('does NOT match inside a URL path', () => {
111
+ const text = 'see https://billing.example.com for details';
112
+ expect(findAliases(text)).toEqual([]);
113
+ });
114
+ it('does NOT match incomplete aliases', () => {
115
+ expect(findAliases('@billing.prod and @billing.prod.')).toEqual([]);
116
+ });
117
+ });
118
+ describe('findAliases — argv mode (permissive)', () => {
119
+ it('matches an alias glued onto a flag prefix', () => {
120
+ const matches = findAliases('-p@billing.prod.db_password', { mode: 'argv' });
121
+ expect(matches).toHaveLength(1);
122
+ expect(matches[0]?.literal).toBe('@billing.prod.db_password');
123
+ });
124
+ it('matches after =', () => {
125
+ const matches = findAliases('--password=@billing.prod.db_password', { mode: 'argv' });
126
+ expect(matches).toHaveLength(1);
127
+ });
128
+ });
129
+ describe('findAliasesInArgv', () => {
130
+ it('groups matches by argv element', () => {
131
+ const argv = ['mysql', '-p@billing.prod.db_password', '-h', '@billing.prod.db_host'];
132
+ const result = findAliasesInArgv(argv);
133
+ expect(result).toHaveLength(2);
134
+ expect(result[0]?.argvIndex).toBe(1);
135
+ expect(result[0]?.matches[0]?.literal).toBe('@billing.prod.db_password');
136
+ expect(result[1]?.argvIndex).toBe(3);
137
+ expect(result[1]?.matches[0]?.literal).toBe('@billing.prod.db_host');
138
+ });
139
+ it('ignores argv elements with no aliases', () => {
140
+ expect(findAliasesInArgv(['echo', 'hello'])).toEqual([]);
141
+ });
142
+ });
143
+ describe('replaceAliases', () => {
144
+ it('substitutes a single alias', () => {
145
+ const result = replaceAliases('@a.b.c', () => 'VALUE');
146
+ expect(result).toBe('VALUE');
147
+ });
148
+ it('substitutes multiple aliases preserving non-alias text', () => {
149
+ const text = 'connect @a.b.c and @x.y.z now';
150
+ const result = replaceAliases(text, (a) => `<${a.project}>`);
151
+ expect(result).toBe('connect <a> and <x> now');
152
+ });
153
+ it('is a no-op when no aliases match', () => {
154
+ expect(replaceAliases('plain text', () => 'X')).toBe('plain text');
155
+ });
156
+ it('preserves email-shaped strings in text mode', () => {
157
+ const text = 'contact support@billing.example.com';
158
+ expect(replaceAliases(text, () => 'X')).toBe(text);
159
+ });
160
+ it('substitutes inside argv-style strings when mode=argv', () => {
161
+ const result = replaceAliases('-p@a.b.c', () => 'PASS', { mode: 'argv' });
162
+ expect(result).toBe('-pPASS');
163
+ });
164
+ it('allows a resolved value that starts with @ + a kebab segment (not an alias)', () => {
165
+ // A real secret value like `@my-token` must pass through unchanged — it
166
+ // is a single segment, not a `@project.env.key` alias literal.
167
+ expect(replaceAliases('@a.b.c', () => '@my-token')).toBe('@my-token');
168
+ expect(replaceAliases('@a.b.c', () => '@2fa-backup')).toBe('@2fa-backup');
169
+ });
170
+ it('throws when a resolved value is itself a fully valid alias (real circularity)', () => {
171
+ expect(() => replaceAliases('@a.b.c', () => '@x.y.z')).toThrow(/circular|valid alias/i);
172
+ });
173
+ });
174
+ describe('buildAlias', () => {
175
+ it('builds a valid alias from components', () => {
176
+ expect(buildAlias({ project: 'billing', environment: 'prod', key: 'db_password' })).toEqual({
177
+ literal: '@billing.prod.db_password',
178
+ project: 'billing',
179
+ environment: 'prod',
180
+ key: 'db_password',
181
+ });
182
+ });
183
+ it('rejects invalid components', () => {
184
+ expect(buildAlias({ project: 'Billing', environment: 'prod', key: 'k' })).toBeNull();
185
+ expect(buildAlias({ project: 'b', environment: '_p', key: 'k' })).toBeNull();
186
+ expect(buildAlias({ project: 'b', environment: 'p', key: 'şifre' })).toBeNull();
187
+ });
188
+ it('accepts uppercase keys', () => {
189
+ expect(buildAlias({ project: 'billing', environment: 'prod', key: 'DATABASE_URL' })).toMatchObject({
190
+ key: 'DATABASE_URL',
191
+ literal: '@billing.prod.DATABASE_URL',
192
+ });
193
+ });
194
+ });
195
+ //# sourceMappingURL=parser.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.test.js","sourceRoot":"","sources":["../../src/reference/parser.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * The decomposed parts of a keynv alias literal `@project.environment.key`.
3
+ *
4
+ * `literal` holds the original string including the leading `@`; `project`,
5
+ * `environment`, and `key` are the validated components.
6
+ */
7
+ export interface Alias {
8
+ readonly literal: string;
9
+ readonly project: string;
10
+ readonly environment: string;
11
+ readonly key: string;
12
+ }
13
+ /**
14
+ * An alias detected inside a larger string, with its byte offsets.
15
+ *
16
+ * `start` is inclusive, `end` is exclusive. `text.slice(start, end)` equals
17
+ * `literal`.
18
+ */
19
+ export interface AliasMatch extends Alias {
20
+ readonly start: number;
21
+ readonly end: number;
22
+ }
23
+ /**
24
+ * Selects how aggressive the finder is.
25
+ *
26
+ * - `'text'` (default): conservative. Aliases preceded by a word character,
27
+ * `.`, `@`, or `/` are rejected, so e.g. `support@billing.example.com`
28
+ * does not produce a false positive.
29
+ * - `'argv'`: permissive. Used when scanning shell argv where flag prefixes
30
+ * like `-p@alias` are common; emails are unlikely.
31
+ */
32
+ export type FindMode = 'text' | 'argv';
33
+ /**
34
+ * Lexical limits for each component of an `@project.environment.key`
35
+ * alias. Exposed here so callers (e.g. validation in the server API)
36
+ * can reuse them.
37
+ */
38
+ export declare const ALIAS_LIMITS: {
39
+ readonly project: {
40
+ readonly min: 1;
41
+ readonly max: 48;
42
+ };
43
+ readonly environment: {
44
+ readonly min: 1;
45
+ readonly max: 24;
46
+ };
47
+ readonly key: {
48
+ readonly min: 1;
49
+ readonly max: 64;
50
+ };
51
+ };
52
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/reference/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAW,SAAQ,KAAK;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAEvC;;;;GAIG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;CAIf,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Lexical limits for each component of an `@project.environment.key`
3
+ * alias. Exposed here so callers (e.g. validation in the server API)
4
+ * can reuse them.
5
+ */
6
+ export const ALIAS_LIMITS = {
7
+ project: { min: 1, max: 48 },
8
+ environment: { min: 1, max: 24 },
9
+ key: { min: 1, max: 64 },
10
+ };
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/reference/types.ts"],"names":[],"mappings":"AAmCA;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,OAAO,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;IAC5B,WAAW,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;IAChC,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;CAChB,CAAC"}