@datacules/agent-identity 0.11.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,109 @@
1
+ Datacules Agent Identity License — Version 1.0
2
+ Copyright (c) 2026 Datacules LLC. All rights reserved.
3
+
4
+ ─────────────────────────────────────────────────────────────────────────────
5
+ PREAMBLE
6
+ ─────────────────────────────────────────────────────────────────────────────
7
+
8
+ This software — Agent Identity & Auth Patterns — is developed and owned by
9
+ Datacules LLC. It is made available to the public as open-source software
10
+ under the permissive terms below.
11
+
12
+ Datacules LLC retains ownership and authorship of this software while
13
+ granting broad, royalty-free rights for anyone to use, copy, modify, and
14
+ distribute it — in commercial or non-commercial contexts — without requiring
15
+ that derivative works also become open source.
16
+
17
+ ─────────────────────────────────────────────────────────────────────────────
18
+ TERMS AND CONDITIONS
19
+ ─────────────────────────────────────────────────────────────────────────────
20
+
21
+ 1. PERMISSION TO USE
22
+
23
+ Permission is hereby granted, free of charge, to any person or
24
+ organization obtaining a copy of this software and associated
25
+ documentation files (the "Software"), to use, copy, modify, merge,
26
+ publish, distribute, sublicense, and/or sell copies of the Software,
27
+ and to permit persons to whom the Software is furnished to do so,
28
+ subject to the conditions below.
29
+
30
+ 2. ATTRIBUTION
31
+
32
+ a. Redistributions of source code must retain this copyright notice,
33
+ this list of conditions, and the disclaimer below.
34
+
35
+ b. Redistributions in binary form or as a product must reproduce this
36
+ copyright notice, this list of conditions, and the disclaimer in the
37
+ documentation and/or other materials provided with the distribution.
38
+
39
+ c. Neither the name "Datacules LLC" nor the names of its contributors
40
+ may be used to endorse or promote products derived from this Software
41
+ without prior written permission from Datacules LLC.
42
+
43
+ 3. COMMERCIAL USE
44
+
45
+ Use of this Software in commercial products, SaaS platforms, internal
46
+ enterprise tools, or any revenue-generating context is explicitly
47
+ permitted without royalty, fee, or additional licensing agreement,
48
+ provided that the conditions in Section 2 (Attribution) are met.
49
+
50
+ 4. NO COPYLEFT / NO VIRAL REQUIREMENT
51
+
52
+ This license does NOT require that derivative works, modifications,
53
+ or software that uses or embeds this Software be made open source.
54
+ You may incorporate this Software into proprietary or closed-source
55
+ products under your own license terms.
56
+
57
+ 5. MODIFICATIONS
58
+
59
+ Modified versions of the Software may be distributed under the same
60
+ terms as this license or under any other permissive open-source
61
+ license (e.g. MIT, Apache 2.0, BSD), provided that:
62
+
63
+ a. The original copyright notice of Datacules LLC is preserved.
64
+ b. Modifications are clearly documented and distinguished from the
65
+ original work.
66
+
67
+ 6. COMPATIBILITY
68
+
69
+ This license is compatible with other permissive open-source licenses
70
+ such as MIT, BSD 2-Clause, BSD 3-Clause, and Apache License 2.0. It
71
+ is also GPL-compatible — this Software may coexist with GPL-licensed
72
+ code, though this Software itself is not distributed under the GPL.
73
+
74
+ ─────────────────────────────────────────────────────────────────────────────
75
+ DISCLAIMER
76
+ ─────────────────────────────────────────────────────────────────────────────
77
+
78
+ THIS SOFTWARE IS PROVIDED BY DATACULES LLC AND CONTRIBUTORS "AS IS" AND
79
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
80
+ IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
81
+ AND NON-INFRINGEMENT ARE DISCLAIMED.
82
+
83
+ IN NO EVENT SHALL DATACULES LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
84
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
85
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
86
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
87
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
88
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
89
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
90
+
91
+ ─────────────────────────────────────────────────────────────────────────────
92
+ SUMMARY (non-binding)
93
+ ─────────────────────────────────────────────────────────────────────────────
94
+
95
+ ✔ Use freely — commercial, proprietary, or open-source projects
96
+ ✔ Modify and distribute with or without changes
97
+ ✔ Sell products built on this Software
98
+ ✔ No royalties or fees
99
+ ✔ No requirement to open-source your own code
100
+ ✔ Attribution to Datacules LLC required in source and binary distributions
101
+ ✗ Do not use "Datacules LLC" to endorse derived products without permission
102
+
103
+ ─────────────────────────────────────────────────────────────────────────────
104
+ CONTACT
105
+ ─────────────────────────────────────────────────────────────────────────────
106
+
107
+ Datacules LLC
108
+ For licensing enquiries: legal@datacules.com
109
+ Product: https://github.com/hvrcharon1/agent-identity
@@ -1,30 +1,79 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DECISION_QUESTIONS = void 0;
3
4
  exports.computeDecision = computeDecision;
5
+ exports.DECISION_QUESTIONS = [
6
+ {
7
+ key: 'variableAccess',
8
+ text: 'Do different users need different levels of access to the same resource?',
9
+ yes: 'Yes — user A can see more than user B',
10
+ no: 'No — all users have identical access',
11
+ },
12
+ {
13
+ key: 'mixedResources',
14
+ text: 'Does the agent access both shared (all-user) and personal (per-user) resources?',
15
+ yes: 'Yes — both kinds in the same agent',
16
+ no: 'No — only one kind',
17
+ },
18
+ {
19
+ key: 'auditRequired',
20
+ text: 'Do you need a per-user audit trail?',
21
+ yes: 'Yes — we need to know which user caused each action',
22
+ no: 'No — agent-level logging is enough',
23
+ // Q3 only affects fixed-access paths. Individual-user-auth and
24
+ // token-exchange inherently carry user identity, so asking about audit
25
+ // trail for those paths would imply an effect that does not exist.
26
+ showIf: (a) => a.variableAccess === false,
27
+ },
28
+ {
29
+ key: 'longTermTokenStorage',
30
+ text: 'Can you store per-user tokens long-term (e.g. in an encrypted DB)?',
31
+ yes: 'Yes — we can persist user tokens securely',
32
+ no: 'No — tokens must be obtained at request time only',
33
+ // Q4 is only relevant when access is variable AND resources are not mixed.
34
+ // For context-switched (variable + mixed) the result is known from Q1+Q2.
35
+ showIf: (a) => a.variableAccess === true && a.mixedResources === false,
36
+ },
37
+ ];
38
+ // ─── Decision engine ──────────────────────────────────────────────────────────
39
+ function make(pattern, label, explanation) {
40
+ return { pattern, label, explanation };
41
+ }
4
42
  function computeDecision(answers) {
5
43
  const { variableAccess, mixedResources, auditRequired, longTermTokenStorage } = answers;
6
- if (variableAccess === null || mixedResources === null || auditRequired === null)
7
- return null;
8
- if (variableAccess && longTermTokenStorage === null)
44
+ // Require Q1 and Q2 before proceeding
45
+ if (variableAccess === null || mixedResources === null)
9
46
  return null;
10
- if (variableAccess && mixedResources) {
11
- return { pattern: 'context-switched', label: 'Hybrid (context-switched)', explanation: 'Your agent needs both fixed credentials for shared resources and user-delegated tokens for personal data. Set explicit routing rules so the agent always knows which to use.' };
12
- }
13
- if (variableAccess && !mixedResources) {
47
+ // ── Variable-access paths ─────────────────────────────────────────────────
48
+ if (variableAccess) {
49
+ if (mixedResources) {
50
+ // Hybrid routing: Q3 and Q4 have no bearing on this pattern.
51
+ // Result is determined by Q1 + Q2 alone.
52
+ return make('context-switched', 'Hybrid (context-switched)', 'Your agent needs both fixed credentials for shared resources and user-delegated tokens for personal data. Set explicit routing rules so the agent always knows which to use.');
53
+ }
54
+ // Variable access, single resource type — Q4 determines token strategy.
55
+ // Gate: Q4 not yet answered.
56
+ if (longTermTokenStorage === null)
57
+ return null;
14
58
  if (!longTermTokenStorage) {
15
- return { pattern: 'token-exchange', label: 'Token exchange / impersonation', explanation: 'You need per-user access but cannot store tokens long-term. Use OAuth token exchange or STS assume-role to get scoped user tokens at request time, without persisting them.' };
59
+ return make('token-exchange', 'Token exchange / impersonation', 'You need per-user access but cannot store tokens long-term. Use OAuth token exchange or STS assume-role to get scoped user tokens at request time, without persisting them.');
16
60
  }
17
- return { pattern: 'individual-user-auth', label: 'Individual user auth', explanation: "Users have different access levels, so each request must carry that user's own token. The agent passes it through; the downstream resource enforces the ACL." };
61
+ return make('individual-user-auth', 'Individual user auth', "Users have different access levels, so each request must carry that user's own token. The agent passes it through; the downstream resource enforces the ACL.");
18
62
  }
19
- if (!variableAccess && mixedResources) {
20
- return { pattern: 'fixed-credential', label: 'Fixed credential with resource-type awareness', explanation: 'All users are equal but the agent accesses different resource types. A single fixed credential works — ensure its scope covers both resource types your agent needs.' };
21
- }
22
- if (!variableAccess && !auditRequired) {
23
- return { pattern: 'fixed-credential', label: 'Fixed credential', explanation: "All users are equal and audit trail isn't critical. A single service account keeps setup simple. Store the key encrypted; never pass it to the model layer." };
63
+ // ── Fixed-access paths (variableAccess = false) ───────────────────────────
64
+ // Q3 (auditRequired) is relevant for every branch below.
65
+ if (auditRequired === null)
66
+ return null;
67
+ if (mixedResources) {
68
+ if (auditRequired) {
69
+ return make('fixed-credential', 'Fixed credential — resource-type awareness + request tagging', "A single service account can access both resource types. Tag each request with the calling user's ID in your own audit log so you have a per-user trace even though the credential is shared.");
70
+ }
71
+ return make('fixed-credential', 'Fixed credential with resource-type awareness', 'All users are equal but the agent accesses different resource types. A single fixed credential works — ensure its scope covers both resource types your agent needs.');
24
72
  }
25
- if (!variableAccess && auditRequired) {
26
- return { pattern: 'fixed-credential', label: 'Fixed credential + request tagging', explanation: "Use a shared service account, but tag each request with the calling user's ID in your own logs. Gives you the simplicity of a fixed credential with an audit trail layer above it." };
73
+ // Single resource type, fixed access
74
+ if (auditRequired) {
75
+ return make('fixed-credential', 'Fixed credential + request tagging', "Use a shared service account, but tag each request with the calling user's ID in your own logs. Gives you the simplicity of a fixed credential with an audit trail layer above it.");
27
76
  }
28
- return null;
77
+ return make('fixed-credential', 'Fixed credential', "All users are equal and audit trail isn't critical. A single service account keeps setup simple. Store the key encrypted; never pass it to the model layer.");
29
78
  }
30
79
  //# sourceMappingURL=decision.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"decision.js","sourceRoot":"","sources":["../../src/decision.ts"],"names":[],"mappings":";;AAEA,0CAyBC;AAzBD,SAAgB,eAAe,CAAC,OAAwB;IACtD,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,oBAAoB,EAAE,GAAG,OAAO,CAAC;IAExF,IAAI,cAAc,KAAK,IAAI,IAAI,cAAc,KAAK,IAAI,IAAI,aAAa,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC9F,IAAI,cAAc,IAAI,oBAAoB,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAEjE,IAAI,cAAc,IAAI,cAAc,EAAE,CAAC;QACrC,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,2BAA2B,EAAE,WAAW,EAAE,8KAA8K,EAAE,CAAC;IAC1Q,CAAC;IACD,IAAI,cAAc,IAAI,CAAC,cAAc,EAAE,CAAC;QACtC,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC1B,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,gCAAgC,EAAE,WAAW,EAAE,6KAA6K,EAAE,CAAC;QAC5Q,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,sBAAsB,EAAE,KAAK,EAAE,sBAAsB,EAAE,WAAW,EAAE,8JAA8J,EAAE,CAAC;IACzP,CAAC;IACD,IAAI,CAAC,cAAc,IAAI,cAAc,EAAE,CAAC;QACtC,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,+CAA+C,EAAE,WAAW,EAAE,sKAAsK,EAAE,CAAC;IACtR,CAAC;IACD,IAAI,CAAC,cAAc,IAAI,CAAC,aAAa,EAAE,CAAC;QACtC,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,6JAA6J,EAAE,CAAC;IAChP,CAAC;IACD,IAAI,CAAC,cAAc,IAAI,aAAa,EAAE,CAAC;QACrC,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,oCAAoC,EAAE,WAAW,EAAE,oLAAoL,EAAE,CAAC;IACzR,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"decision.js","sourceRoot":"","sources":["../../src/decision.ts"],"names":[],"mappings":";;;AA0EA,0CAqEC;AA7GY,QAAA,kBAAkB,GAAuB;IACpD;QACE,GAAG,EAAE,gBAAgB;QACrB,IAAI,EAAE,0EAA0E;QAChF,GAAG,EAAE,uCAAuC;QAC5C,EAAE,EAAE,sCAAsC;KAC3C;IACD;QACE,GAAG,EAAE,gBAAgB;QACrB,IAAI,EAAE,iFAAiF;QACvF,GAAG,EAAE,oCAAoC;QACzC,EAAE,EAAE,oBAAoB;KACzB;IACD;QACE,GAAG,EAAE,eAAe;QACpB,IAAI,EAAE,qCAAqC;QAC3C,GAAG,EAAE,qDAAqD;QAC1D,EAAE,EAAE,oCAAoC;QACxC,+DAA+D;QAC/D,uEAAuE;QACvE,mEAAmE;QACnE,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,KAAK,KAAK;KAC1C;IACD;QACE,GAAG,EAAE,sBAAsB;QAC3B,IAAI,EAAE,oEAAoE;QAC1E,GAAG,EAAE,2CAA2C;QAChD,EAAE,EAAE,mDAAmD;QACvD,2EAA2E;QAC3E,0EAA0E;QAC1E,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,KAAK,IAAI,IAAI,CAAC,CAAC,cAAc,KAAK,KAAK;KACvE;CACF,CAAC;AAEF,iFAAiF;AAEjF,SAAS,IAAI,CAAC,OAAwB,EAAE,KAAa,EAAE,WAAmB;IACxE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;AACzC,CAAC;AAED,SAAgB,eAAe,CAAC,OAAwB;IACtD,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,oBAAoB,EAAE,GAAG,OAAO,CAAC;IAExF,sCAAsC;IACtC,IAAI,cAAc,KAAK,IAAI,IAAI,cAAc,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAEpE,6EAA6E;IAE7E,IAAI,cAAc,EAAE,CAAC;QACnB,IAAI,cAAc,EAAE,CAAC;YACnB,6DAA6D;YAC7D,yCAAyC;YACzC,OAAO,IAAI,CACT,kBAAkB,EAClB,2BAA2B,EAC3B,8KAA8K,CAC/K,CAAC;QACJ,CAAC;QAED,wEAAwE;QACxE,6BAA6B;QAC7B,IAAI,oBAAoB,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAE/C,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC1B,OAAO,IAAI,CACT,gBAAgB,EAChB,gCAAgC,EAChC,6KAA6K,CAC9K,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CACT,sBAAsB,EACtB,sBAAsB,EACtB,8JAA8J,CAC/J,CAAC;IACJ,CAAC;IAED,6EAA6E;IAC7E,yDAAyD;IACzD,IAAI,aAAa,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAExC,IAAI,cAAc,EAAE,CAAC;QACnB,IAAI,aAAa,EAAE,CAAC;YAClB,OAAO,IAAI,CACT,kBAAkB,EAClB,8DAA8D,EAC9D,+LAA+L,CAChM,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CACT,kBAAkB,EAClB,+CAA+C,EAC/C,sKAAsK,CACvK,CAAC;IACJ,CAAC;IAED,qCAAqC;IACrC,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,IAAI,CACT,kBAAkB,EAClB,oCAAoC,EACpC,oLAAoL,CACrL,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CACT,kBAAkB,EAClB,kBAAkB,EAClB,6JAA6J,CAC9J,CAAC;AACJ,CAAC"}
@@ -1,33 +1,62 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CredentialRotationScheduler = void 0;
4
- // ─── CredentialRotationScheduler ───────────────────────────────────────────────
4
+ // ─── CredentialRotationScheduler ──────────────────────────────────────────────
5
5
  class CredentialRotationScheduler {
6
- constructor(repository, auditLogger) {
6
+ constructor(repository, auditLogger, getUsageCount) {
7
7
  this.repository = repository;
8
8
  this.auditLogger = auditLogger;
9
+ this.getUsageCount = getUsageCount;
9
10
  this.providers = new Map();
10
11
  this.intervalHandle = null;
12
+ /**
13
+ * Tracks credentials that are inside their post-rotation grace window.
14
+ * During the window, the old ref is still valid for in-flight requests
15
+ * (resolved externally via getGraceRef()), and no new rotation is triggered.
16
+ */
17
+ this.graceWindows = new Map();
18
+ }
19
+ /** Alternate constructor from an options object. */
20
+ static fromOptions(opts) {
21
+ return new CredentialRotationScheduler(opts.repository, opts.auditLogger, opts.getUsageCount);
11
22
  }
12
23
  registerProvider(provider) {
13
24
  this.providers.set(provider.id, provider);
14
25
  }
15
26
  /**
16
- * Check all active credentials for pending rotation and rotate them.
17
- * Call this on a schedule (e.g. every hour via cron or setInterval).
27
+ * Returns true when a credential is inside its post-rotation grace window.
28
+ * Expired entries are pruned on read.
18
29
  */
30
+ inGracePeriod(credentialId) {
31
+ const grace = this.graceWindows.get(credentialId);
32
+ if (!grace)
33
+ return false;
34
+ if (grace.endsAt > Date.now())
35
+ return true;
36
+ this.graceWindows.delete(credentialId);
37
+ return false;
38
+ }
39
+ /**
40
+ * Returns the OLD credential ref while the grace window is active, or null.
41
+ * Use this in routers that need to accept both the old and new ref during
42
+ * the post-rotation handover period (e.g. for in-flight HTTP requests).
43
+ */
44
+ getGraceRef(credentialId) {
45
+ const grace = this.graceWindows.get(credentialId);
46
+ return grace && grace.endsAt > Date.now() ? grace.oldRef : null;
47
+ }
19
48
  async runOnce() {
20
49
  const credentials = await this.repository.listActive();
21
50
  const now = new Date();
22
51
  for (const cred of credentials) {
23
- // Skip credentials with no rotation policy
24
52
  if (!cred.rotation)
25
53
  continue;
26
- // Skip unclaimed auth.md credentials — they cannot be rotated until
27
- // the claim ceremony is complete and status flips to 'active'
28
54
  if (cred.status === 'unclaimed')
29
55
  continue;
30
- const due = this.isRotationDue(cred, cred.rotation, now);
56
+ // Skip when inside the grace window from a recent rotation
57
+ if (this.inGracePeriod(cred.id))
58
+ continue;
59
+ const due = await this.isRotationDue(cred, cred.rotation, now);
31
60
  if (!due) {
32
61
  await this.maybeEmitWarning(cred, cred.rotation, now);
33
62
  continue;
@@ -41,6 +70,14 @@ class CredentialRotationScheduler {
41
70
  }
42
71
  try {
43
72
  const { newRef, rotatedAt } = await provider.rotate(cred);
73
+ // Record the grace window BEFORE updating the store so any in-flight
74
+ // resolution holding the old ref can still resolve cleanly.
75
+ if (cred.rotation.gracePeriodSeconds && cred.rotation.gracePeriodSeconds > 0) {
76
+ this.graceWindows.set(cred.id, {
77
+ oldRef: cred.ref,
78
+ endsAt: Date.now() + cred.rotation.gracePeriodSeconds * 1000,
79
+ });
80
+ }
44
81
  await this.repository.update(cred.id, { ref: newRef, lastRotated: rotatedAt });
45
82
  if (this.auditLogger) {
46
83
  await this.auditLogger.log({
@@ -78,10 +115,6 @@ class CredentialRotationScheduler {
78
115
  }
79
116
  }
80
117
  }
81
- /**
82
- * Start a background rotation loop at the given interval.
83
- * @param intervalMs Check frequency in milliseconds (default: 3600000 = 1 hour)
84
- */
85
118
  start(intervalMs = 3600000) {
86
119
  if (this.intervalHandle !== null)
87
120
  return;
@@ -95,21 +128,29 @@ class CredentialRotationScheduler {
95
128
  this.intervalHandle = null;
96
129
  }
97
130
  }
98
- isRotationDue(cred, policy, now) {
131
+ async isRotationDue(cred, policy, now) {
132
+ // Days-based rotation
99
133
  if (policy.rotateAfterDays !== undefined && cred.lastRotated) {
100
- const lastRotated = new Date(cred.lastRotated);
101
- const daysSince = (now.getTime() - lastRotated.getTime()) / 86400000;
134
+ const daysSince = (now.getTime() - new Date(cred.lastRotated).getTime()) / 86400000;
102
135
  if (daysSince >= policy.rotateAfterDays)
103
136
  return true;
104
137
  }
138
+ // Uses-based rotation — requires a getUsageCount callback
139
+ if (policy.rotateAfterUses !== undefined && this.getUsageCount) {
140
+ const count = await this.getUsageCount(cred.id);
141
+ if (count >= policy.rotateAfterUses)
142
+ return true;
143
+ }
105
144
  return false;
106
145
  }
107
146
  async maybeEmitWarning(cred, policy, now) {
108
147
  if (!this.auditLogger)
109
148
  return;
110
- if (policy.notifyBeforeDays !== undefined && policy.rotateAfterDays !== undefined && cred.lastRotated) {
111
- const lastRotated = new Date(cred.lastRotated);
112
- const daysUntilDue = policy.rotateAfterDays - (now.getTime() - lastRotated.getTime()) / 86400000;
149
+ if (policy.notifyBeforeDays !== undefined &&
150
+ policy.rotateAfterDays !== undefined &&
151
+ cred.lastRotated) {
152
+ const daysUntilDue = policy.rotateAfterDays -
153
+ (now.getTime() - new Date(cred.lastRotated).getTime()) / 86400000;
113
154
  if (daysUntilDue > 0 && daysUntilDue <= policy.notifyBeforeDays) {
114
155
  await this.auditLogger.log({
115
156
  timestamp: new Date().toISOString(),
@@ -1 +1 @@
1
- {"version":3,"file":"rotation.js","sourceRoot":"","sources":["../../src/rotation.ts"],"names":[],"mappings":";;;AA+BA,kFAAkF;AAElF,MAAa,2BAA2B;IAItC,YACmB,UAA8B,EAC9B,WAAyB;QADzB,eAAU,GAAV,UAAU,CAAoB;QAC9B,gBAAW,GAAX,WAAW,CAAc;QAL3B,cAAS,GAAG,IAAI,GAAG,EAA4B,CAAC;QACzD,mBAAc,GAA0C,IAAI,CAAC;IAKlE,CAAC;IAEJ,gBAAgB,CAAC,QAA0B;QACzC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,OAAO;QACX,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC;QACvD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QAEvB,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;YAC/B,2CAA2C;YAC3C,IAAI,CAAC,IAAI,CAAC,QAAQ;gBAAE,SAAS;YAE7B,oEAAoE;YACpE,8DAA8D;YAC9D,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW;gBAAE,SAAS;YAE1C,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YACzD,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;gBACtD,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW;gBACxC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;gBAC/C,CAAC,CAAC,IAAI,CAAC;YAET,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,CAAC,IAAI,CAAC,kDAAkD,IAAI,CAAC,EAAE,kBAAkB,IAAI,CAAC,QAAQ,CAAC,WAAW,IAAI,OAAO,GAAG,CAAC,CAAC;gBACjI,SAAS;YACX,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC1D,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC;gBAE/E,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;oBACrB,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;wBACzB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;wBACnC,OAAO,EAAE,YAAY,IAAI,CAAC,EAAE,EAAE;wBAC9B,MAAM,EAAE,QAAQ;wBAChB,MAAM,EAAE,oBAAoB;wBAC5B,UAAU,EAAE,IAAI,CAAC,EAAE;wBACnB,YAAY,EAAE,QAAQ;wBACtB,QAAQ,EAAE,OAAO;wBACjB,KAAK,EAAE,QAAQ;wBACf,YAAY,EAAE,IAAI,CAAC,EAAE;wBACrB,cAAc,EAAE,IAAI,CAAC,IAAI;wBACzB,WAAW,EAAE,QAAQ;qBACtB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,2CAA2C,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;gBAC1E,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;oBACrB,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;wBACzB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;wBACnC,OAAO,EAAE,YAAY,IAAI,CAAC,EAAE,EAAE;wBAC9B,MAAM,EAAE,QAAQ;wBAChB,MAAM,EAAE,4BAA4B;wBACpC,UAAU,EAAE,IAAI,CAAC,EAAE;wBACnB,YAAY,EAAE,QAAQ;wBACtB,QAAQ,EAAE,OAAO;wBACjB,KAAK,EAAE,QAAQ;wBACf,YAAY,EAAE,IAAI,CAAC,EAAE;wBACrB,cAAc,EAAE,IAAI,CAAC,IAAI;wBACzB,WAAW,EAAE,QAAQ;qBACtB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU,GAAG,OAAS;QAC1B,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI;YAAE,OAAO;QACzC,IAAI,CAAC,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE;YACrC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC,EAAE,UAAU,CAAC,CAAC;IACjB,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI,EAAE,CAAC;YACjC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACnC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC7B,CAAC;IACH,CAAC;IAEO,aAAa,CAAC,IAAgB,EAAE,MAAsB,EAAE,GAAS;QACvE,IAAI,MAAM,CAAC,eAAe,KAAK,SAAS,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAC7D,MAAM,WAAW,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC/C,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,WAAW,CAAC,OAAO,EAAE,CAAC,GAAG,QAAU,CAAC;YACvE,IAAI,SAAS,IAAI,MAAM,CAAC,eAAe;gBAAE,OAAO,IAAI,CAAC;QACvD,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,IAAgB,EAAE,MAAsB,EAAE,GAAS;QAChF,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,OAAO;QAC9B,IAAI,MAAM,CAAC,gBAAgB,KAAK,SAAS,IAAI,MAAM,CAAC,eAAe,KAAK,SAAS,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACtG,MAAM,WAAW,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC/C,MAAM,YAAY,GAAG,MAAM,CAAC,eAAe,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,WAAW,CAAC,OAAO,EAAE,CAAC,GAAG,QAAU,CAAC;YACnG,IAAI,YAAY,GAAG,CAAC,IAAI,YAAY,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;gBAChE,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;oBACzB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;oBACnC,OAAO,EAAE,oBAAoB,IAAI,CAAC,EAAE,EAAE;oBACtC,MAAM,EAAE,QAAQ;oBAChB,MAAM,EAAE,yBAAyB;oBACjC,UAAU,EAAE,IAAI,CAAC,EAAE;oBACnB,YAAY,EAAE,QAAQ;oBACtB,QAAQ,EAAE,OAAO;oBACjB,KAAK,EAAE,QAAQ;oBACf,YAAY,EAAE,IAAI,CAAC,EAAE;oBACrB,cAAc,EAAE,IAAI,CAAC,IAAI;oBACzB,WAAW,EAAE,QAAQ;iBACtB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;CACF;AArID,kEAqIC"}
1
+ {"version":3,"file":"rotation.js","sourceRoot":"","sources":["../../src/rotation.ts"],"names":[],"mappings":"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"}
@@ -1,27 +1,75 @@
1
+ export const DECISION_QUESTIONS = [
2
+ {
3
+ key: 'variableAccess',
4
+ text: 'Do different users need different levels of access to the same resource?',
5
+ yes: 'Yes — user A can see more than user B',
6
+ no: 'No — all users have identical access',
7
+ },
8
+ {
9
+ key: 'mixedResources',
10
+ text: 'Does the agent access both shared (all-user) and personal (per-user) resources?',
11
+ yes: 'Yes — both kinds in the same agent',
12
+ no: 'No — only one kind',
13
+ },
14
+ {
15
+ key: 'auditRequired',
16
+ text: 'Do you need a per-user audit trail?',
17
+ yes: 'Yes — we need to know which user caused each action',
18
+ no: 'No — agent-level logging is enough',
19
+ // Q3 only affects fixed-access paths. Individual-user-auth and
20
+ // token-exchange inherently carry user identity, so asking about audit
21
+ // trail for those paths would imply an effect that does not exist.
22
+ showIf: (a) => a.variableAccess === false,
23
+ },
24
+ {
25
+ key: 'longTermTokenStorage',
26
+ text: 'Can you store per-user tokens long-term (e.g. in an encrypted DB)?',
27
+ yes: 'Yes — we can persist user tokens securely',
28
+ no: 'No — tokens must be obtained at request time only',
29
+ // Q4 is only relevant when access is variable AND resources are not mixed.
30
+ // For context-switched (variable + mixed) the result is known from Q1+Q2.
31
+ showIf: (a) => a.variableAccess === true && a.mixedResources === false,
32
+ },
33
+ ];
34
+ // ─── Decision engine ──────────────────────────────────────────────────────────
35
+ function make(pattern, label, explanation) {
36
+ return { pattern, label, explanation };
37
+ }
1
38
  export function computeDecision(answers) {
2
39
  const { variableAccess, mixedResources, auditRequired, longTermTokenStorage } = answers;
3
- if (variableAccess === null || mixedResources === null || auditRequired === null)
4
- return null;
5
- if (variableAccess && longTermTokenStorage === null)
40
+ // Require Q1 and Q2 before proceeding
41
+ if (variableAccess === null || mixedResources === null)
6
42
  return null;
7
- if (variableAccess && mixedResources) {
8
- return { pattern: 'context-switched', label: 'Hybrid (context-switched)', explanation: 'Your agent needs both fixed credentials for shared resources and user-delegated tokens for personal data. Set explicit routing rules so the agent always knows which to use.' };
9
- }
10
- if (variableAccess && !mixedResources) {
43
+ // ── Variable-access paths ─────────────────────────────────────────────────
44
+ if (variableAccess) {
45
+ if (mixedResources) {
46
+ // Hybrid routing: Q3 and Q4 have no bearing on this pattern.
47
+ // Result is determined by Q1 + Q2 alone.
48
+ return make('context-switched', 'Hybrid (context-switched)', 'Your agent needs both fixed credentials for shared resources and user-delegated tokens for personal data. Set explicit routing rules so the agent always knows which to use.');
49
+ }
50
+ // Variable access, single resource type — Q4 determines token strategy.
51
+ // Gate: Q4 not yet answered.
52
+ if (longTermTokenStorage === null)
53
+ return null;
11
54
  if (!longTermTokenStorage) {
12
- return { pattern: 'token-exchange', label: 'Token exchange / impersonation', explanation: 'You need per-user access but cannot store tokens long-term. Use OAuth token exchange or STS assume-role to get scoped user tokens at request time, without persisting them.' };
55
+ return make('token-exchange', 'Token exchange / impersonation', 'You need per-user access but cannot store tokens long-term. Use OAuth token exchange or STS assume-role to get scoped user tokens at request time, without persisting them.');
13
56
  }
14
- return { pattern: 'individual-user-auth', label: 'Individual user auth', explanation: "Users have different access levels, so each request must carry that user's own token. The agent passes it through; the downstream resource enforces the ACL." };
57
+ return make('individual-user-auth', 'Individual user auth', "Users have different access levels, so each request must carry that user's own token. The agent passes it through; the downstream resource enforces the ACL.");
15
58
  }
16
- if (!variableAccess && mixedResources) {
17
- return { pattern: 'fixed-credential', label: 'Fixed credential with resource-type awareness', explanation: 'All users are equal but the agent accesses different resource types. A single fixed credential works — ensure its scope covers both resource types your agent needs.' };
18
- }
19
- if (!variableAccess && !auditRequired) {
20
- return { pattern: 'fixed-credential', label: 'Fixed credential', explanation: "All users are equal and audit trail isn't critical. A single service account keeps setup simple. Store the key encrypted; never pass it to the model layer." };
59
+ // ── Fixed-access paths (variableAccess = false) ───────────────────────────
60
+ // Q3 (auditRequired) is relevant for every branch below.
61
+ if (auditRequired === null)
62
+ return null;
63
+ if (mixedResources) {
64
+ if (auditRequired) {
65
+ return make('fixed-credential', 'Fixed credential — resource-type awareness + request tagging', "A single service account can access both resource types. Tag each request with the calling user's ID in your own audit log so you have a per-user trace even though the credential is shared.");
66
+ }
67
+ return make('fixed-credential', 'Fixed credential with resource-type awareness', 'All users are equal but the agent accesses different resource types. A single fixed credential works — ensure its scope covers both resource types your agent needs.');
21
68
  }
22
- if (!variableAccess && auditRequired) {
23
- return { pattern: 'fixed-credential', label: 'Fixed credential + request tagging', explanation: "Use a shared service account, but tag each request with the calling user's ID in your own logs. Gives you the simplicity of a fixed credential with an audit trail layer above it." };
69
+ // Single resource type, fixed access
70
+ if (auditRequired) {
71
+ return make('fixed-credential', 'Fixed credential + request tagging', "Use a shared service account, but tag each request with the calling user's ID in your own logs. Gives you the simplicity of a fixed credential with an audit trail layer above it.");
24
72
  }
25
- return null;
73
+ return make('fixed-credential', 'Fixed credential', "All users are equal and audit trail isn't critical. A single service account keeps setup simple. Store the key encrypted; never pass it to the model layer.");
26
74
  }
27
75
  //# sourceMappingURL=decision.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"decision.js","sourceRoot":"","sources":["../../src/decision.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAAC,OAAwB;IACtD,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,oBAAoB,EAAE,GAAG,OAAO,CAAC;IAExF,IAAI,cAAc,KAAK,IAAI,IAAI,cAAc,KAAK,IAAI,IAAI,aAAa,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC9F,IAAI,cAAc,IAAI,oBAAoB,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAEjE,IAAI,cAAc,IAAI,cAAc,EAAE,CAAC;QACrC,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,2BAA2B,EAAE,WAAW,EAAE,8KAA8K,EAAE,CAAC;IAC1Q,CAAC;IACD,IAAI,cAAc,IAAI,CAAC,cAAc,EAAE,CAAC;QACtC,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC1B,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,gCAAgC,EAAE,WAAW,EAAE,6KAA6K,EAAE,CAAC;QAC5Q,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,sBAAsB,EAAE,KAAK,EAAE,sBAAsB,EAAE,WAAW,EAAE,8JAA8J,EAAE,CAAC;IACzP,CAAC;IACD,IAAI,CAAC,cAAc,IAAI,cAAc,EAAE,CAAC;QACtC,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,+CAA+C,EAAE,WAAW,EAAE,sKAAsK,EAAE,CAAC;IACtR,CAAC;IACD,IAAI,CAAC,cAAc,IAAI,CAAC,aAAa,EAAE,CAAC;QACtC,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,6JAA6J,EAAE,CAAC;IAChP,CAAC;IACD,IAAI,CAAC,cAAc,IAAI,aAAa,EAAE,CAAC;QACrC,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,oCAAoC,EAAE,WAAW,EAAE,oLAAoL,EAAE,CAAC;IACzR,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"decision.js","sourceRoot":"","sources":["../../src/decision.ts"],"names":[],"mappings":"AAkCA,MAAM,CAAC,MAAM,kBAAkB,GAAuB;IACpD;QACE,GAAG,EAAE,gBAAgB;QACrB,IAAI,EAAE,0EAA0E;QAChF,GAAG,EAAE,uCAAuC;QAC5C,EAAE,EAAE,sCAAsC;KAC3C;IACD;QACE,GAAG,EAAE,gBAAgB;QACrB,IAAI,EAAE,iFAAiF;QACvF,GAAG,EAAE,oCAAoC;QACzC,EAAE,EAAE,oBAAoB;KACzB;IACD;QACE,GAAG,EAAE,eAAe;QACpB,IAAI,EAAE,qCAAqC;QAC3C,GAAG,EAAE,qDAAqD;QAC1D,EAAE,EAAE,oCAAoC;QACxC,+DAA+D;QAC/D,uEAAuE;QACvE,mEAAmE;QACnE,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,KAAK,KAAK;KAC1C;IACD;QACE,GAAG,EAAE,sBAAsB;QAC3B,IAAI,EAAE,oEAAoE;QAC1E,GAAG,EAAE,2CAA2C;QAChD,EAAE,EAAE,mDAAmD;QACvD,2EAA2E;QAC3E,0EAA0E;QAC1E,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,KAAK,IAAI,IAAI,CAAC,CAAC,cAAc,KAAK,KAAK;KACvE;CACF,CAAC;AAEF,iFAAiF;AAEjF,SAAS,IAAI,CAAC,OAAwB,EAAE,KAAa,EAAE,WAAmB;IACxE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAwB;IACtD,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,oBAAoB,EAAE,GAAG,OAAO,CAAC;IAExF,sCAAsC;IACtC,IAAI,cAAc,KAAK,IAAI,IAAI,cAAc,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAEpE,6EAA6E;IAE7E,IAAI,cAAc,EAAE,CAAC;QACnB,IAAI,cAAc,EAAE,CAAC;YACnB,6DAA6D;YAC7D,yCAAyC;YACzC,OAAO,IAAI,CACT,kBAAkB,EAClB,2BAA2B,EAC3B,8KAA8K,CAC/K,CAAC;QACJ,CAAC;QAED,wEAAwE;QACxE,6BAA6B;QAC7B,IAAI,oBAAoB,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAE/C,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC1B,OAAO,IAAI,CACT,gBAAgB,EAChB,gCAAgC,EAChC,6KAA6K,CAC9K,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CACT,sBAAsB,EACtB,sBAAsB,EACtB,8JAA8J,CAC/J,CAAC;IACJ,CAAC;IAED,6EAA6E;IAC7E,yDAAyD;IACzD,IAAI,aAAa,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAExC,IAAI,cAAc,EAAE,CAAC;QACnB,IAAI,aAAa,EAAE,CAAC;YAClB,OAAO,IAAI,CACT,kBAAkB,EAClB,8DAA8D,EAC9D,+LAA+L,CAChM,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CACT,kBAAkB,EAClB,+CAA+C,EAC/C,sKAAsK,CACvK,CAAC;IACJ,CAAC;IAED,qCAAqC;IACrC,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,IAAI,CACT,kBAAkB,EAClB,oCAAoC,EACpC,oLAAoL,CACrL,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CACT,kBAAkB,EAClB,kBAAkB,EAClB,6JAA6J,CAC9J,CAAC;AACJ,CAAC"}
@@ -1,30 +1,59 @@
1
- // ─── CredentialRotationScheduler ───────────────────────────────────────────────
1
+ // ─── CredentialRotationScheduler ──────────────────────────────────────────────
2
2
  export class CredentialRotationScheduler {
3
- constructor(repository, auditLogger) {
3
+ constructor(repository, auditLogger, getUsageCount) {
4
4
  this.repository = repository;
5
5
  this.auditLogger = auditLogger;
6
+ this.getUsageCount = getUsageCount;
6
7
  this.providers = new Map();
7
8
  this.intervalHandle = null;
9
+ /**
10
+ * Tracks credentials that are inside their post-rotation grace window.
11
+ * During the window, the old ref is still valid for in-flight requests
12
+ * (resolved externally via getGraceRef()), and no new rotation is triggered.
13
+ */
14
+ this.graceWindows = new Map();
15
+ }
16
+ /** Alternate constructor from an options object. */
17
+ static fromOptions(opts) {
18
+ return new CredentialRotationScheduler(opts.repository, opts.auditLogger, opts.getUsageCount);
8
19
  }
9
20
  registerProvider(provider) {
10
21
  this.providers.set(provider.id, provider);
11
22
  }
12
23
  /**
13
- * Check all active credentials for pending rotation and rotate them.
14
- * Call this on a schedule (e.g. every hour via cron or setInterval).
24
+ * Returns true when a credential is inside its post-rotation grace window.
25
+ * Expired entries are pruned on read.
15
26
  */
27
+ inGracePeriod(credentialId) {
28
+ const grace = this.graceWindows.get(credentialId);
29
+ if (!grace)
30
+ return false;
31
+ if (grace.endsAt > Date.now())
32
+ return true;
33
+ this.graceWindows.delete(credentialId);
34
+ return false;
35
+ }
36
+ /**
37
+ * Returns the OLD credential ref while the grace window is active, or null.
38
+ * Use this in routers that need to accept both the old and new ref during
39
+ * the post-rotation handover period (e.g. for in-flight HTTP requests).
40
+ */
41
+ getGraceRef(credentialId) {
42
+ const grace = this.graceWindows.get(credentialId);
43
+ return grace && grace.endsAt > Date.now() ? grace.oldRef : null;
44
+ }
16
45
  async runOnce() {
17
46
  const credentials = await this.repository.listActive();
18
47
  const now = new Date();
19
48
  for (const cred of credentials) {
20
- // Skip credentials with no rotation policy
21
49
  if (!cred.rotation)
22
50
  continue;
23
- // Skip unclaimed auth.md credentials — they cannot be rotated until
24
- // the claim ceremony is complete and status flips to 'active'
25
51
  if (cred.status === 'unclaimed')
26
52
  continue;
27
- const due = this.isRotationDue(cred, cred.rotation, now);
53
+ // Skip when inside the grace window from a recent rotation
54
+ if (this.inGracePeriod(cred.id))
55
+ continue;
56
+ const due = await this.isRotationDue(cred, cred.rotation, now);
28
57
  if (!due) {
29
58
  await this.maybeEmitWarning(cred, cred.rotation, now);
30
59
  continue;
@@ -38,6 +67,14 @@ export class CredentialRotationScheduler {
38
67
  }
39
68
  try {
40
69
  const { newRef, rotatedAt } = await provider.rotate(cred);
70
+ // Record the grace window BEFORE updating the store so any in-flight
71
+ // resolution holding the old ref can still resolve cleanly.
72
+ if (cred.rotation.gracePeriodSeconds && cred.rotation.gracePeriodSeconds > 0) {
73
+ this.graceWindows.set(cred.id, {
74
+ oldRef: cred.ref,
75
+ endsAt: Date.now() + cred.rotation.gracePeriodSeconds * 1000,
76
+ });
77
+ }
41
78
  await this.repository.update(cred.id, { ref: newRef, lastRotated: rotatedAt });
42
79
  if (this.auditLogger) {
43
80
  await this.auditLogger.log({
@@ -75,10 +112,6 @@ export class CredentialRotationScheduler {
75
112
  }
76
113
  }
77
114
  }
78
- /**
79
- * Start a background rotation loop at the given interval.
80
- * @param intervalMs Check frequency in milliseconds (default: 3600000 = 1 hour)
81
- */
82
115
  start(intervalMs = 3600000) {
83
116
  if (this.intervalHandle !== null)
84
117
  return;
@@ -92,21 +125,29 @@ export class CredentialRotationScheduler {
92
125
  this.intervalHandle = null;
93
126
  }
94
127
  }
95
- isRotationDue(cred, policy, now) {
128
+ async isRotationDue(cred, policy, now) {
129
+ // Days-based rotation
96
130
  if (policy.rotateAfterDays !== undefined && cred.lastRotated) {
97
- const lastRotated = new Date(cred.lastRotated);
98
- const daysSince = (now.getTime() - lastRotated.getTime()) / 86400000;
131
+ const daysSince = (now.getTime() - new Date(cred.lastRotated).getTime()) / 86400000;
99
132
  if (daysSince >= policy.rotateAfterDays)
100
133
  return true;
101
134
  }
135
+ // Uses-based rotation — requires a getUsageCount callback
136
+ if (policy.rotateAfterUses !== undefined && this.getUsageCount) {
137
+ const count = await this.getUsageCount(cred.id);
138
+ if (count >= policy.rotateAfterUses)
139
+ return true;
140
+ }
102
141
  return false;
103
142
  }
104
143
  async maybeEmitWarning(cred, policy, now) {
105
144
  if (!this.auditLogger)
106
145
  return;
107
- if (policy.notifyBeforeDays !== undefined && policy.rotateAfterDays !== undefined && cred.lastRotated) {
108
- const lastRotated = new Date(cred.lastRotated);
109
- const daysUntilDue = policy.rotateAfterDays - (now.getTime() - lastRotated.getTime()) / 86400000;
146
+ if (policy.notifyBeforeDays !== undefined &&
147
+ policy.rotateAfterDays !== undefined &&
148
+ cred.lastRotated) {
149
+ const daysUntilDue = policy.rotateAfterDays -
150
+ (now.getTime() - new Date(cred.lastRotated).getTime()) / 86400000;
110
151
  if (daysUntilDue > 0 && daysUntilDue <= policy.notifyBeforeDays) {
111
152
  await this.auditLogger.log({
112
153
  timestamp: new Date().toISOString(),
@@ -1 +1 @@
1
- {"version":3,"file":"rotation.js","sourceRoot":"","sources":["../../src/rotation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rotation.js","sourceRoot":"","sources":["../../src/rotation.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,33 @@
1
+ /**
2
+ * Decision helper — recommends an auth pattern based on user answers.
3
+ *
4
+ * Fixes applied in this version:
5
+ * 1. Q4 null-guard moved inside the variableAccess && !mixedResources branch —
6
+ * context-switched no longer gates on an unused Q4 answer.
7
+ * 2. Q3 (auditRequired) is now consulted on ALL fixed-access paths, including
8
+ * the !variableAccess && mixedResources case. Previously Q3 was silently
9
+ * ignored there, producing the same result regardless of audit requirement.
10
+ * 3. New distinct result label: 'resource-type awareness + request tagging'
11
+ * for !variableAccess && mixedResources && auditRequired.
12
+ * 4. DECISION_QUESTIONS exported here (moved from DecisionTab.tsx) so the
13
+ * question set can be tested independently of React and imported by the UI.
14
+ * 5. Q3 showIf: variableAccess === false — question is hidden and never asked
15
+ * on variable-access paths where it has no effect.
16
+ * 6. Q4 showIf: variableAccess === true && mixedResources === false —
17
+ * context-switched path (variable + mixed) no longer surfaces Q4.
18
+ */
1
19
  import type { DecisionAnswers, DecisionResult } from './types';
20
+ export interface DecisionQuestion {
21
+ key: keyof DecisionAnswers;
22
+ text: string;
23
+ yes: string;
24
+ no: string;
25
+ /**
26
+ * When present, the question is only shown (and therefore only required)
27
+ * when the predicate returns true. Hidden questions do NOT gate the result.
28
+ */
29
+ showIf?: (a: DecisionAnswers) => boolean;
30
+ }
31
+ export declare const DECISION_QUESTIONS: DecisionQuestion[];
2
32
  export declare function computeDecision(answers: DecisionAnswers): DecisionResult | null;
3
33
  //# sourceMappingURL=decision.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"decision.d.ts","sourceRoot":"","sources":["../../src/decision.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE/D,wBAAgB,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,cAAc,GAAG,IAAI,CAyB/E"}
1
+ {"version":3,"file":"decision.d.ts","sourceRoot":"","sources":["../../src/decision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAmB,MAAM,SAAS,CAAC;AAIhF,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,eAAe,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,eAAe,KAAK,OAAO,CAAC;CAC1C;AAED,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,EAgChD,CAAC;AAQF,wBAAgB,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,cAAc,GAAG,IAAI,CAqE/E"}
@@ -1,16 +1,17 @@
1
1
  /**
2
2
  * Automated Credential Rotation — Feature #4 from FEATURE_SUGGESTIONS.md
3
3
  *
4
- * RotationPolicy on Credential + CredentialRotationScheduler that detects
5
- * expiring/due credentials and calls registered RotationProvider instances
6
- * to mint new secrets.
4
+ * Additions in this version:
5
+ * - rotateAfterUses: optional getUsageCount callback; isRotationDue() is now
6
+ * async so it can query usage counts alongside the days check.
7
+ * - Grace period: graceWindows Map tracks old ref for gracePeriodSeconds after
8
+ * a successful rotation. runOnce() skips re-rotation while in the window.
9
+ * inGracePeriod() and getGraceRef() are public so routers can accept both
10
+ * the old and new ref during the handover window.
11
+ * - RotationSchedulerOptions interface + static fromOptions() factory.
12
+ * - Constructor is backwards-compatible: getUsageCount is an optional third param.
7
13
  */
8
14
  import type { Credential, AuditLogger } from './types';
9
- /**
10
- * A RotationProvider mints a new secret for a credential and updates the
11
- * store. Built-in providers: VaultRotationProvider, AwsRotationProvider.
12
- * Custom providers implement this interface.
13
- */
14
15
  export interface RotationProvider {
15
16
  id: string;
16
17
  rotate(credential: Credential): Promise<{
@@ -18,31 +19,48 @@ export interface RotationProvider {
18
19
  rotatedAt: string;
19
20
  }>;
20
21
  }
21
- /**
22
- * CredentialRepository is a minimal interface over any CredentialStore that
23
- * supports mutation — listing and updating credentials. The core store
24
- * interface is read-only for callers; rotation needs write access.
25
- */
26
22
  export interface RotationRepository {
27
23
  listActive(): Promise<Credential[]>;
28
24
  update(id: string, patch: Partial<Credential>): Promise<void>;
29
25
  }
26
+ export interface RotationSchedulerOptions {
27
+ repository: RotationRepository;
28
+ auditLogger?: AuditLogger;
29
+ /**
30
+ * Returns how many times a credential has been used since its last rotation.
31
+ * Required for rotateAfterUses enforcement. Typically delegates to a usage
32
+ * counter maintained alongside audit events or budget tracking.
33
+ */
34
+ getUsageCount?: (credentialId: string) => Promise<number>;
35
+ }
30
36
  export declare class CredentialRotationScheduler {
31
37
  private readonly repository;
32
38
  private readonly auditLogger?;
39
+ private readonly getUsageCount?;
33
40
  private readonly providers;
34
41
  private intervalHandle;
35
- constructor(repository: RotationRepository, auditLogger?: AuditLogger | undefined);
42
+ /**
43
+ * Tracks credentials that are inside their post-rotation grace window.
44
+ * During the window, the old ref is still valid for in-flight requests
45
+ * (resolved externally via getGraceRef()), and no new rotation is triggered.
46
+ */
47
+ private readonly graceWindows;
48
+ constructor(repository: RotationRepository, auditLogger?: AuditLogger | undefined, getUsageCount?: ((credentialId: string) => Promise<number>) | undefined);
49
+ /** Alternate constructor from an options object. */
50
+ static fromOptions(opts: RotationSchedulerOptions): CredentialRotationScheduler;
36
51
  registerProvider(provider: RotationProvider): void;
37
52
  /**
38
- * Check all active credentials for pending rotation and rotate them.
39
- * Call this on a schedule (e.g. every hour via cron or setInterval).
53
+ * Returns true when a credential is inside its post-rotation grace window.
54
+ * Expired entries are pruned on read.
40
55
  */
41
- runOnce(): Promise<void>;
56
+ inGracePeriod(credentialId: string): boolean;
42
57
  /**
43
- * Start a background rotation loop at the given interval.
44
- * @param intervalMs Check frequency in milliseconds (default: 3600000 = 1 hour)
58
+ * Returns the OLD credential ref while the grace window is active, or null.
59
+ * Use this in routers that need to accept both the old and new ref during
60
+ * the post-rotation handover period (e.g. for in-flight HTTP requests).
45
61
  */
62
+ getGraceRef(credentialId: string): string | null;
63
+ runOnce(): Promise<void>;
46
64
  start(intervalMs?: number): void;
47
65
  stop(): void;
48
66
  private isRotationDue;
@@ -1 +1 @@
1
- {"version":3,"file":"rotation.d.ts","sourceRoot":"","sources":["../../src/rotation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAkB,MAAM,SAAS,CAAC;AAIvE;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChF;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IACpC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/D;AAID,qBAAa,2BAA2B;IAKpC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAL/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IACjE,OAAO,CAAC,cAAc,CAA+C;gBAGlD,UAAU,EAAE,kBAAkB,EAC9B,WAAW,CAAC,EAAE,WAAW,YAAA;IAG5C,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAIlD;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAmE9B;;;OAGG;IACH,KAAK,CAAC,UAAU,SAAY,GAAG,IAAI;IAOnC,IAAI,IAAI,IAAI;IAOZ,OAAO,CAAC,aAAa;YASP,gBAAgB;CAsB/B"}
1
+ {"version":3,"file":"rotation.d.ts","sourceRoot":"","sources":["../../src/rotation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAkB,MAAM,SAAS,CAAC;AAIvE,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChF;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IACpC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,kBAAkB,CAAC;IAC/B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC3D;AAID,qBAAa,2BAA2B;IAYpC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAC7B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;IAbjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IACjE,OAAO,CAAC,cAAc,CAA+C;IAErE;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAyD;gBAGnE,UAAU,EAAE,kBAAkB,EAC9B,WAAW,CAAC,EAAE,WAAW,YAAA,EACzB,aAAa,CAAC,GAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,aAAA;IAG5E,oDAAoD;IACpD,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,wBAAwB,GAAG,2BAA2B;IAI/E,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAIlD;;;OAGG;IACH,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAQ5C;;;;OAIG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAK1C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA8E9B,KAAK,CAAC,UAAU,SAAY,GAAG,IAAI;IAOnC,IAAI,IAAI,IAAI;YAOE,aAAa;YAgBb,gBAAgB;CA2B/B"}
@@ -27,15 +27,15 @@ export declare const RotationPolicySchema: z.ZodObject<{
27
27
  provisioner: z.ZodOptional<z.ZodString>;
28
28
  }, "strip", z.ZodTypeAny, {
29
29
  provisioner?: string | undefined;
30
+ gracePeriodSeconds?: number | undefined;
30
31
  rotateAfterDays?: number | undefined;
31
32
  rotateAfterUses?: number | undefined;
32
- gracePeriodSeconds?: number | undefined;
33
33
  notifyBeforeDays?: number | undefined;
34
34
  }, {
35
35
  provisioner?: string | undefined;
36
+ gracePeriodSeconds?: number | undefined;
36
37
  rotateAfterDays?: number | undefined;
37
38
  rotateAfterUses?: number | undefined;
38
- gracePeriodSeconds?: number | undefined;
39
39
  notifyBeforeDays?: number | undefined;
40
40
  }>;
41
41
  export declare const BudgetPolicySchema: z.ZodObject<{
@@ -133,15 +133,15 @@ export declare const CredentialSchema: z.ZodObject<{
133
133
  provisioner: z.ZodOptional<z.ZodString>;
134
134
  }, "strip", z.ZodTypeAny, {
135
135
  provisioner?: string | undefined;
136
+ gracePeriodSeconds?: number | undefined;
136
137
  rotateAfterDays?: number | undefined;
137
138
  rotateAfterUses?: number | undefined;
138
- gracePeriodSeconds?: number | undefined;
139
139
  notifyBeforeDays?: number | undefined;
140
140
  }, {
141
141
  provisioner?: string | undefined;
142
+ gracePeriodSeconds?: number | undefined;
142
143
  rotateAfterDays?: number | undefined;
143
144
  rotateAfterUses?: number | undefined;
144
- gracePeriodSeconds?: number | undefined;
145
145
  notifyBeforeDays?: number | undefined;
146
146
  }>>;
147
147
  budget: z.ZodOptional<z.ZodObject<{
@@ -181,9 +181,9 @@ export declare const CredentialSchema: z.ZodObject<{
181
181
  rotationIntervalDays?: number | undefined;
182
182
  rotation?: {
183
183
  provisioner?: string | undefined;
184
+ gracePeriodSeconds?: number | undefined;
184
185
  rotateAfterDays?: number | undefined;
185
186
  rotateAfterUses?: number | undefined;
186
- gracePeriodSeconds?: number | undefined;
187
187
  notifyBeforeDays?: number | undefined;
188
188
  } | undefined;
189
189
  budget?: {
@@ -211,9 +211,9 @@ export declare const CredentialSchema: z.ZodObject<{
211
211
  rotationIntervalDays?: number | undefined;
212
212
  rotation?: {
213
213
  provisioner?: string | undefined;
214
+ gracePeriodSeconds?: number | undefined;
214
215
  rotateAfterDays?: number | undefined;
215
216
  rotateAfterUses?: number | undefined;
216
- gracePeriodSeconds?: number | undefined;
217
217
  notifyBeforeDays?: number | undefined;
218
218
  } | undefined;
219
219
  budget?: {
@@ -448,15 +448,15 @@ export declare const TrustedIdentityProviderSchema: z.ZodObject<{
448
448
  requiredAmr: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
449
449
  enabled: z.ZodOptional<z.ZodBoolean>;
450
450
  }, "strip", z.ZodTypeAny, {
451
- label: string;
452
451
  issuerUrl: string;
452
+ label: string;
453
453
  enabled?: boolean | undefined;
454
454
  requiredAmr?: string[] | undefined;
455
455
  jwksUri?: string | undefined;
456
456
  cimdUri?: string | undefined;
457
457
  }, {
458
- label: string;
459
458
  issuerUrl: string;
459
+ label: string;
460
460
  enabled?: boolean | undefined;
461
461
  requiredAmr?: string[] | undefined;
462
462
  jwksUri?: string | undefined;
@@ -471,15 +471,15 @@ export declare const TrustedProviderRegistrySchema: z.ZodObject<{
471
471
  requiredAmr: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
472
472
  enabled: z.ZodOptional<z.ZodBoolean>;
473
473
  }, "strip", z.ZodTypeAny, {
474
- label: string;
475
474
  issuerUrl: string;
475
+ label: string;
476
476
  enabled?: boolean | undefined;
477
477
  requiredAmr?: string[] | undefined;
478
478
  jwksUri?: string | undefined;
479
479
  cimdUri?: string | undefined;
480
480
  }, {
481
- label: string;
482
481
  issuerUrl: string;
482
+ label: string;
483
483
  enabled?: boolean | undefined;
484
484
  requiredAmr?: string[] | undefined;
485
485
  jwksUri?: string | undefined;
@@ -489,8 +489,8 @@ export declare const TrustedProviderRegistrySchema: z.ZodObject<{
489
489
  jwksCacheFloorMs: z.ZodOptional<z.ZodNumber>;
490
490
  }, "strip", z.ZodTypeAny, {
491
491
  providers: {
492
- label: string;
493
492
  issuerUrl: string;
493
+ label: string;
494
494
  enabled?: boolean | undefined;
495
495
  requiredAmr?: string[] | undefined;
496
496
  jwksUri?: string | undefined;
@@ -500,8 +500,8 @@ export declare const TrustedProviderRegistrySchema: z.ZodObject<{
500
500
  jwksCacheFloorMs?: number | undefined;
501
501
  }, {
502
502
  providers: {
503
- label: string;
504
503
  issuerUrl: string;
504
+ label: string;
505
505
  enabled?: boolean | undefined;
506
506
  requiredAmr?: string[] | undefined;
507
507
  jwksUri?: string | undefined;
package/package.json CHANGED
@@ -1,10 +1,21 @@
1
1
  {
2
2
  "name": "@datacules/agent-identity",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "private": false,
5
5
  "description": "Provider-agnostic credential routing and identity management for AI agents",
6
6
  "author": "Datacules LLC",
7
- "license": "MIT",
7
+ "license": "SEE LICENSE IN LICENSE",
8
+ "keywords": [
9
+ "agent-identity",
10
+ "credential-routing",
11
+ "ai-agents",
12
+ "identity",
13
+ "oauth",
14
+ "zero-trust",
15
+ "audit",
16
+ "provider-agnostic",
17
+ "datacules"
18
+ ],
8
19
  "repository": {
9
20
  "type": "git",
10
21
  "url": "https://github.com/hvrcharon1/agent-identity.git",
@@ -31,7 +42,8 @@
31
42
  },
32
43
  "files": [
33
44
  "dist",
34
- "README.md"
45
+ "README.md",
46
+ "LICENSE"
35
47
  ],
36
48
  "scripts": {
37
49
  "build": "tsc -p tsconfig.build.json && tsc -p tsconfig.cjs.json",