@penclipai/server 2026.508.2 → 2026.511.0-canary.0

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 (192) hide show
  1. package/dist/adapters/builtin-adapter-types.d.ts.map +1 -1
  2. package/dist/adapters/builtin-adapter-types.js +1 -0
  3. package/dist/adapters/builtin-adapter-types.js.map +1 -1
  4. package/dist/adapters/registry.d.ts.map +1 -1
  5. package/dist/adapters/registry.js +17 -0
  6. package/dist/adapters/registry.js.map +1 -1
  7. package/dist/config.js +4 -4
  8. package/dist/config.js.map +1 -1
  9. package/dist/home-paths.d.ts +8 -11
  10. package/dist/home-paths.d.ts.map +1 -1
  11. package/dist/home-paths.js +14 -67
  12. package/dist/home-paths.js.map +1 -1
  13. package/dist/routes/agents.d.ts.map +1 -1
  14. package/dist/routes/agents.js +8 -0
  15. package/dist/routes/agents.js.map +1 -1
  16. package/dist/routes/environments.d.ts.map +1 -1
  17. package/dist/routes/environments.js +8 -1
  18. package/dist/routes/environments.js.map +1 -1
  19. package/dist/routes/plugins.d.ts.map +1 -1
  20. package/dist/routes/plugins.js +6 -0
  21. package/dist/routes/plugins.js.map +1 -1
  22. package/dist/routes/projects.d.ts.map +1 -1
  23. package/dist/routes/projects.js +6 -0
  24. package/dist/routes/projects.js.map +1 -1
  25. package/dist/routes/secrets.d.ts.map +1 -1
  26. package/dist/routes/secrets.js +269 -5
  27. package/dist/routes/secrets.js.map +1 -1
  28. package/dist/secrets/aws-secrets-manager-provider.d.ts +87 -0
  29. package/dist/secrets/aws-secrets-manager-provider.d.ts.map +1 -0
  30. package/dist/secrets/aws-secrets-manager-provider.js +748 -0
  31. package/dist/secrets/aws-secrets-manager-provider.js.map +1 -0
  32. package/dist/secrets/configured-provider.d.ts +3 -0
  33. package/dist/secrets/configured-provider.d.ts.map +1 -0
  34. package/dist/secrets/configured-provider.js +8 -0
  35. package/dist/secrets/configured-provider.js.map +1 -0
  36. package/dist/secrets/external-stub-providers.d.ts.map +1 -1
  37. package/dist/secrets/external-stub-providers.js +55 -5
  38. package/dist/secrets/external-stub-providers.js.map +1 -1
  39. package/dist/secrets/local-encrypted-provider.d.ts.map +1 -1
  40. package/dist/secrets/local-encrypted-provider.js +140 -12
  41. package/dist/secrets/local-encrypted-provider.js.map +1 -1
  42. package/dist/secrets/provider-registry.d.ts +2 -1
  43. package/dist/secrets/provider-registry.d.ts.map +1 -1
  44. package/dist/secrets/provider-registry.js +6 -2
  45. package/dist/secrets/provider-registry.js.map +1 -1
  46. package/dist/secrets/types.d.ts +117 -8
  47. package/dist/secrets/types.d.ts.map +1 -1
  48. package/dist/secrets/types.js +35 -1
  49. package/dist/secrets/types.js.map +1 -1
  50. package/dist/services/access.d.ts +27 -27
  51. package/dist/services/activity.d.ts +8 -8
  52. package/dist/services/agents.d.ts +9 -9
  53. package/dist/services/approvals.d.ts +10 -10
  54. package/dist/services/assets.d.ts +3 -3
  55. package/dist/services/board-auth.d.ts +24 -24
  56. package/dist/services/environment-config.d.ts +14 -2
  57. package/dist/services/environment-config.d.ts.map +1 -1
  58. package/dist/services/environment-config.js +57 -4
  59. package/dist/services/environment-config.js.map +1 -1
  60. package/dist/services/environment-execution-target.d.ts.map +1 -1
  61. package/dist/services/environment-execution-target.js +2 -0
  62. package/dist/services/environment-execution-target.js.map +1 -1
  63. package/dist/services/environment-runtime.d.ts.map +1 -1
  64. package/dist/services/environment-runtime.js +10 -2
  65. package/dist/services/environment-runtime.js.map +1 -1
  66. package/dist/services/feedback.d.ts +4 -4
  67. package/dist/services/finance.d.ts +8 -8
  68. package/dist/services/goals.d.ts +20 -20
  69. package/dist/services/heartbeat.d.ts +24 -19
  70. package/dist/services/heartbeat.d.ts.map +1 -1
  71. package/dist/services/heartbeat.js +82 -8
  72. package/dist/services/heartbeat.js.map +1 -1
  73. package/dist/services/inbox-dismissals.d.ts +2 -2
  74. package/dist/services/issue-approvals.d.ts +2 -2
  75. package/dist/services/issue-continuation-summary.d.ts +2 -0
  76. package/dist/services/issue-continuation-summary.d.ts.map +1 -1
  77. package/dist/services/issue-continuation-summary.js +10 -0
  78. package/dist/services/issue-continuation-summary.js.map +1 -1
  79. package/dist/services/issues.d.ts +18 -18
  80. package/dist/services/plugin-environment-driver.d.ts +6 -6
  81. package/dist/services/plugin-host-services.d.ts.map +1 -1
  82. package/dist/services/plugin-host-services.js +31 -4
  83. package/dist/services/plugin-host-services.js.map +1 -1
  84. package/dist/services/plugin-local-folders.d.ts +1 -0
  85. package/dist/services/plugin-local-folders.d.ts.map +1 -1
  86. package/dist/services/plugin-local-folders.js +45 -0
  87. package/dist/services/plugin-local-folders.js.map +1 -1
  88. package/dist/services/plugin-managed-agents.d.ts.map +1 -1
  89. package/dist/services/plugin-managed-agents.js +52 -9
  90. package/dist/services/plugin-managed-agents.js.map +1 -1
  91. package/dist/services/plugin-managed-skills.d.ts +14 -0
  92. package/dist/services/plugin-managed-skills.d.ts.map +1 -0
  93. package/dist/services/plugin-managed-skills.js +264 -0
  94. package/dist/services/plugin-managed-skills.js.map +1 -0
  95. package/dist/services/plugin-registry.d.ts +79 -79
  96. package/dist/services/plugin-secrets-handler.d.ts +2 -0
  97. package/dist/services/plugin-secrets-handler.d.ts.map +1 -1
  98. package/dist/services/plugin-secrets-handler.js +17 -80
  99. package/dist/services/plugin-secrets-handler.js.map +1 -1
  100. package/dist/services/recovery/service.d.ts +61 -0
  101. package/dist/services/recovery/service.d.ts.map +1 -1
  102. package/dist/services/recovery/service.js +63 -17
  103. package/dist/services/recovery/service.js.map +1 -1
  104. package/dist/services/routines.d.ts +18 -18
  105. package/dist/services/routines.d.ts.map +1 -1
  106. package/dist/services/routines.js +36 -4
  107. package/dist/services/routines.js.map +1 -1
  108. package/dist/services/secrets.d.ts +1566 -119
  109. package/dist/services/secrets.d.ts.map +1 -1
  110. package/dist/services/secrets.js +1465 -69
  111. package/dist/services/secrets.js.map +1 -1
  112. package/package.json +17 -16
  113. package/ui-dist/assets/{_basePickBy-5H35nb2M.js → _basePickBy-B0S0WJuO.js} +1 -1
  114. package/ui-dist/assets/{_baseUniq-BqsDtPj4.js → _baseUniq-DPfwHtaX.js} +1 -1
  115. package/ui-dist/assets/{arc-F3f4deZD.js → arc-dayO-_vQ.js} +1 -1
  116. package/ui-dist/assets/{architectureDiagram-VXUJARFQ-pBm1fRMv.js → architectureDiagram-VXUJARFQ-B7gjpAgc.js} +1 -1
  117. package/ui-dist/assets/{blockDiagram-VD42YOAC-CGtc9RP7.js → blockDiagram-VD42YOAC-e0_AbQkY.js} +1 -1
  118. package/ui-dist/assets/{browser-ponyfill-CkdJVj1i.js → browser-ponyfill-D5A0IJkC.js} +1 -1
  119. package/ui-dist/assets/{c4Diagram-YG6GDRKO-BXgVj8GH.js → c4Diagram-YG6GDRKO-D5OdXvo8.js} +1 -1
  120. package/ui-dist/assets/channel-BLi0LFH0.js +1 -0
  121. package/ui-dist/assets/{chunk-4BX2VUAB-Ds1Y5IYA.js → chunk-4BX2VUAB-uWBbpQP3.js} +1 -1
  122. package/ui-dist/assets/{chunk-55IACEB6-D8GwRmXK.js → chunk-55IACEB6-CFVDvwbd.js} +1 -1
  123. package/ui-dist/assets/{chunk-B4BG7PRW-R_v5U6_B.js → chunk-B4BG7PRW-Niy3z_vf.js} +1 -1
  124. package/ui-dist/assets/{chunk-DI55MBZ5-DO4X9EFt.js → chunk-DI55MBZ5-BSFdxpNJ.js} +1 -1
  125. package/ui-dist/assets/{chunk-FMBD7UC4-DUu61Scs.js → chunk-FMBD7UC4-Npjz_-5M.js} +1 -1
  126. package/ui-dist/assets/{chunk-QN33PNHL-Bw2VuHcK.js → chunk-QN33PNHL-C2BptvDe.js} +1 -1
  127. package/ui-dist/assets/{chunk-QZHKN3VN-BMGdo5T7.js → chunk-QZHKN3VN-B_lJernK.js} +1 -1
  128. package/ui-dist/assets/{chunk-TZMSLE5B-Cj_cdifl.js → chunk-TZMSLE5B-CNK1gBxt.js} +1 -1
  129. package/ui-dist/assets/classDiagram-2ON5EDUG-DGtCZCaT.js +1 -0
  130. package/ui-dist/assets/classDiagram-v2-WZHVMYZB-DGtCZCaT.js +1 -0
  131. package/ui-dist/assets/clone-_FFZ0Kkl.js +1 -0
  132. package/ui-dist/assets/{cose-bilkent-S5V4N54A-3YDaxa6o.js → cose-bilkent-S5V4N54A-P5AbZ8TB.js} +1 -1
  133. package/ui-dist/assets/{dagre-6UL2VRFP-CmLvQKQL.js → dagre-6UL2VRFP-Byky8_ia.js} +1 -1
  134. package/ui-dist/assets/{diagram-PSM6KHXK-vZK9KPBu.js → diagram-PSM6KHXK-fWgBJ_Sk.js} +1 -1
  135. package/ui-dist/assets/{diagram-QEK2KX5R-Bu9JBN1e.js → diagram-QEK2KX5R-Di6U-VgU.js} +1 -1
  136. package/ui-dist/assets/{diagram-S2PKOQOG-gPR1ps4Q.js → diagram-S2PKOQOG--ALJobJP.js} +1 -1
  137. package/ui-dist/assets/{erDiagram-Q2GNP2WA-BpqETGGN.js → erDiagram-Q2GNP2WA-BPLxxd-8.js} +1 -1
  138. package/ui-dist/assets/{flowDiagram-NV44I4VS-B0iV5Bcy.js → flowDiagram-NV44I4VS-DsKtnwgY.js} +1 -1
  139. package/ui-dist/assets/{ganttDiagram-JELNMOA3-BxQL_kP7.js → ganttDiagram-JELNMOA3-D-RgqRnI.js} +1 -1
  140. package/ui-dist/assets/{gitGraphDiagram-V2S2FVAM-CSsc-XDT.js → gitGraphDiagram-V2S2FVAM-B9hWxZno.js} +1 -1
  141. package/ui-dist/assets/{graph-DWnTQd3e.js → graph-BR5K_DHH.js} +1 -1
  142. package/ui-dist/assets/{index-BEfD-NrI.js → index--jhL8HjG.js} +1 -1
  143. package/ui-dist/assets/{index-C24lwrRh.js → index-3FxOnh1Q.js} +1 -1
  144. package/ui-dist/assets/{index-CqFa1_Kx.js → index-B5iG7mfQ.js} +1 -1
  145. package/ui-dist/assets/{index-DRqmQ4ym.js → index-BC-VyJRT.js} +1 -1
  146. package/ui-dist/assets/{index-mfdF2CPG.js → index-BKJKSfwf.js} +1 -1
  147. package/ui-dist/assets/{index-DNyOAFyR.js → index-BP2zDr7N.js} +1 -1
  148. package/ui-dist/assets/{index-CmZ6XLj-.js → index-BVZZDphv.js} +1 -1
  149. package/ui-dist/assets/{index-DbsPCpm_.js → index-Bi7Lez4i.js} +1 -1
  150. package/ui-dist/assets/{index-CpOa4tDv.js → index-C5zaTUz3.js} +1 -1
  151. package/ui-dist/assets/index-CJyKYByK.js +538 -0
  152. package/ui-dist/assets/index-COTa6xTk.css +1 -0
  153. package/ui-dist/assets/{index-Dt3jXp2D.js → index-CP1her1A.js} +1 -1
  154. package/ui-dist/assets/{index-h9lpZQKL.js → index-CPBqNjLU.js} +1 -1
  155. package/ui-dist/assets/{index-CxnOSxK9.js → index-CY4Sacam.js} +1 -1
  156. package/ui-dist/assets/{index-DgU-HHpm.js → index-CrCHtJt9.js} +1 -1
  157. package/ui-dist/assets/{index-C3xGHm3G.js → index-D-kP_TCS.js} +1 -1
  158. package/ui-dist/assets/{index-Bw88aPGu.js → index-D0b0bdp9.js} +1 -1
  159. package/ui-dist/assets/{index-CaFk2kgt.js → index-DDo7a1ad.js} +1 -1
  160. package/ui-dist/assets/{index-Ckh-TE03.js → index-F8dNHc7L.js} +1 -1
  161. package/ui-dist/assets/{index-DUerGXI8.js → index-GIT3T29G.js} +1 -1
  162. package/ui-dist/assets/{index-DiPyhXNL.js → index-Ii2Zu1VC.js} +1 -1
  163. package/ui-dist/assets/{index-DvOzQrgz.js → index-cAXY17Km.js} +1 -1
  164. package/ui-dist/assets/{index-CzxxXvnl.js → index-vL5R__U-.js} +1 -1
  165. package/ui-dist/assets/{index-DNgm4Hx7.js → index-xy3NppqB.js} +1 -1
  166. package/ui-dist/assets/{infoDiagram-HS3SLOUP-C9a-DRdF.js → infoDiagram-HS3SLOUP-Cw5FMQPy.js} +1 -1
  167. package/ui-dist/assets/{journeyDiagram-XKPGCS4Q-Cu752PhZ.js → journeyDiagram-XKPGCS4Q-qqubogM5.js} +1 -1
  168. package/ui-dist/assets/{kanban-definition-3W4ZIXB7-PXy7IffE.js → kanban-definition-3W4ZIXB7-BHKa2WJW.js} +1 -1
  169. package/ui-dist/assets/{layout-Ci-UJJNd.js → layout-n4Wr5yzd.js} +1 -1
  170. package/ui-dist/assets/{linear-D8Qy6J5I.js → linear-BeRJXNne.js} +1 -1
  171. package/ui-dist/assets/{mermaid.core-RTrr9erR.js → mermaid.core-DelVCbRr.js} +4 -4
  172. package/ui-dist/assets/{mindmap-definition-VGOIOE7T-Ad_ky9GS.js → mindmap-definition-VGOIOE7T-DR-YsecJ.js} +1 -1
  173. package/ui-dist/assets/{pieDiagram-ADFJNKIX-BPWjI8Sm.js → pieDiagram-ADFJNKIX-CZXfqZBG.js} +1 -1
  174. package/ui-dist/assets/{quadrantDiagram-AYHSOK5B-DxY-Cew9.js → quadrantDiagram-AYHSOK5B-BBl26L66.js} +1 -1
  175. package/ui-dist/assets/{requirementDiagram-UZGBJVZJ-BiUlKNuF.js → requirementDiagram-UZGBJVZJ-CvVYsxxA.js} +1 -1
  176. package/ui-dist/assets/{sankeyDiagram-TZEHDZUN-t3mfJhUj.js → sankeyDiagram-TZEHDZUN-BVw2uYFt.js} +1 -1
  177. package/ui-dist/assets/{sequenceDiagram-WL72ISMW-D90qw9a6.js → sequenceDiagram-WL72ISMW--kspLpct.js} +1 -1
  178. package/ui-dist/assets/{stateDiagram-FKZM4ZOC-DB70vjUm.js → stateDiagram-FKZM4ZOC-DPx02LV8.js} +1 -1
  179. package/ui-dist/assets/stateDiagram-v2-4FDKWEC3-S-NvEffl.js +1 -0
  180. package/ui-dist/assets/{timeline-definition-IT6M3QCI-CYSOqO3s.js → timeline-definition-IT6M3QCI-CyMnn5_z.js} +1 -1
  181. package/ui-dist/assets/{treemap-GDKQZRPO-QqfwsQzN.js → treemap-GDKQZRPO-DwLh53A5.js} +1 -1
  182. package/ui-dist/assets/{xychartDiagram-PRI3JC2R-DZuSZ892.js → xychartDiagram-PRI3JC2R-xX5JJ2_4.js} +1 -1
  183. package/ui-dist/index.html +2 -2
  184. package/ui-dist/locales/en/common.json +629 -0
  185. package/ui-dist/locales/zh-CN/common.json +551 -0
  186. package/ui-dist/assets/channel-BklDDvhc.js +0 -1
  187. package/ui-dist/assets/classDiagram-2ON5EDUG-gSWbQXsC.js +0 -1
  188. package/ui-dist/assets/classDiagram-v2-WZHVMYZB-gSWbQXsC.js +0 -1
  189. package/ui-dist/assets/clone-BhrAR33H.js +0 -1
  190. package/ui-dist/assets/index-GwA57FCP.js +0 -537
  191. package/ui-dist/assets/index-RH-ttKJp.css +0 -1
  192. package/ui-dist/assets/stateDiagram-v2-4FDKWEC3-WlT0xb9j.js +0 -1
@@ -0,0 +1,748 @@
1
+ import { createHash, createHmac } from "node:crypto";
2
+ import { S3Client } from "@aws-sdk/client-s3";
3
+ import { unprocessable } from "../errors.js";
4
+ import { SecretProviderClientError } from "./types.js";
5
+ const AWS_SECRETS_MANAGER_SCHEME = "aws_secrets_manager_v1";
6
+ const DEFAULT_PREFIX = "paperclip";
7
+ const DEFAULT_OWNER_TAG = "paperclip";
8
+ const DEFAULT_VERSION_STAGE = "AWSCURRENT";
9
+ const PAPERCLIP_PENDING_VERSION_STAGE = "PAPERCLIP_PENDING";
10
+ const DEFAULT_DELETE_RECOVERY_WINDOW_DAYS = 30;
11
+ const AWS_SECRETS_MANAGER_REQUEST_TIMEOUT_MS = 30_000;
12
+ const AWS_CREDENTIAL_CACHE_TTL_MS = 5 * 60_000;
13
+ const AWS_CREDENTIAL_EXPIRATION_SKEW_MS = 60_000;
14
+ const AWS_RUNTIME_CREDENTIAL_WARNING = "AWS bootstrap credentials must be available to the Paperclip server runtime through the AWS SDK default credential provider chain: IAM role/workload identity, AWS_PROFILE/SSO/shared credentials, web identity, container/instance metadata, or short-lived shell credentials.";
15
+ const AWS_CREDENTIAL_CUSTODY_WARNING = "Do not store AWS root credentials or long-lived IAM user access keys in Paperclip company_secrets; the AWS provider bootstrap belongs in deployment infrastructure, the process environment, an AWS profile, or the orchestrator secret store.";
16
+ const awsCredentialProviders = new Map();
17
+ function sha256Hex(value) {
18
+ return createHash("sha256").update(value).digest("hex");
19
+ }
20
+ function hmac(key, value) {
21
+ return createHmac("sha256", key).update(value).digest();
22
+ }
23
+ function awsDateParts(now = new Date()) {
24
+ const iso = now.toISOString().replace(/[:-]|\.\d{3}/g, "");
25
+ return {
26
+ amzDate: iso,
27
+ dateStamp: iso.slice(0, 8),
28
+ };
29
+ }
30
+ function canonicalHeaderValue(value) {
31
+ return value.trim().replace(/\s+/g, " ");
32
+ }
33
+ function signAwsSecretsManagerRequest(input) {
34
+ const { amzDate, dateStamp } = awsDateParts();
35
+ const payloadHash = sha256Hex(input.body);
36
+ const headers = {
37
+ "content-type": "application/x-amz-json-1.1",
38
+ host: input.endpoint.host,
39
+ "x-amz-content-sha256": payloadHash,
40
+ "x-amz-date": amzDate,
41
+ "x-amz-target": `secretsmanager.${input.operation}`,
42
+ };
43
+ if (input.credentials.sessionToken) {
44
+ headers["x-amz-security-token"] = input.credentials.sessionToken;
45
+ }
46
+ const sortedHeaderNames = Object.keys(headers).sort();
47
+ const canonicalHeaders = sortedHeaderNames
48
+ .map((name) => `${name}:${canonicalHeaderValue(headers[name] ?? "")}\n`)
49
+ .join("");
50
+ const signedHeaders = sortedHeaderNames.join(";");
51
+ const canonicalRequest = [
52
+ "POST",
53
+ input.endpoint.pathname || "/",
54
+ "",
55
+ canonicalHeaders,
56
+ signedHeaders,
57
+ payloadHash,
58
+ ].join("\n");
59
+ const credentialScope = `${dateStamp}/${input.region}/secretsmanager/aws4_request`;
60
+ const stringToSign = [
61
+ "AWS4-HMAC-SHA256",
62
+ amzDate,
63
+ credentialScope,
64
+ sha256Hex(canonicalRequest),
65
+ ].join("\n");
66
+ const dateKey = hmac(`AWS4${input.credentials.secretAccessKey}`, dateStamp);
67
+ const regionKey = hmac(dateKey, input.region);
68
+ const serviceKey = hmac(regionKey, "secretsmanager");
69
+ const signingKey = hmac(serviceKey, "aws4_request");
70
+ const signature = createHmac("sha256", signingKey).update(stringToSign).digest("hex");
71
+ return {
72
+ ...headers,
73
+ authorization: `AWS4-HMAC-SHA256 Credential=${input.credentials.accessKeyId}/${credentialScope}, ` +
74
+ `SignedHeaders=${signedHeaders}, Signature=${signature}`,
75
+ };
76
+ }
77
+ async function loadAwsCredentials(region) {
78
+ const now = Date.now();
79
+ let cached = awsCredentialProviders.get(region);
80
+ if (!cached) {
81
+ // S3Client is only used as a carrier for the AWS SDK default credential provider chain.
82
+ // No S3 API calls are made here; switch to defaultProvider({ region }) if we add that dependency.
83
+ cached = {
84
+ client: new S3Client({ region }),
85
+ credentials: null,
86
+ expiresAt: 0,
87
+ pending: null,
88
+ };
89
+ awsCredentialProviders.set(region, cached);
90
+ }
91
+ if (cached.credentials && cached.expiresAt > now)
92
+ return cached.credentials;
93
+ if (cached.pending)
94
+ return cached.pending;
95
+ cached.pending = (async () => {
96
+ const credentialSource = cached.client.config.credentials;
97
+ const credentials = typeof credentialSource === "function"
98
+ ? await credentialSource()
99
+ : await credentialSource;
100
+ if (!credentials?.accessKeyId || !credentials.secretAccessKey) {
101
+ throw new Error("AWS SDK default credential provider chain did not return credentials");
102
+ }
103
+ const resolved = {
104
+ accessKeyId: credentials.accessKeyId,
105
+ secretAccessKey: credentials.secretAccessKey,
106
+ sessionToken: credentials.sessionToken,
107
+ };
108
+ const expiration = credentials.expiration?.getTime();
109
+ cached.credentials = resolved;
110
+ cached.expiresAt = Math.min(now + AWS_CREDENTIAL_CACHE_TTL_MS, expiration ? expiration - AWS_CREDENTIAL_EXPIRATION_SKEW_MS : Number.POSITIVE_INFINITY);
111
+ return resolved;
112
+ })().finally(() => {
113
+ if (cached)
114
+ cached.pending = null;
115
+ });
116
+ return cached.pending;
117
+ }
118
+ function configuredAwsSecretsManagerDescriptor() {
119
+ return {
120
+ id: "aws_secrets_manager",
121
+ label: "AWS Secrets Manager",
122
+ requiresExternalRef: false,
123
+ supportsManagedValues: true,
124
+ supportsExternalReferences: true,
125
+ configured: canLoadAwsSecretsManagerConfig(),
126
+ };
127
+ }
128
+ function canLoadAwsSecretsManagerConfig() {
129
+ return getAwsConfigReadiness().missingConfig.length === 0;
130
+ }
131
+ function asOptionalNonEmptyString(value) {
132
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
133
+ }
134
+ function readProviderVaultConfig(input) {
135
+ if (input.provider !== "aws_secrets_manager") {
136
+ throw unprocessable("AWS Secrets Manager provider received a mismatched provider vault");
137
+ }
138
+ if (input.status === "disabled") {
139
+ throw unprocessable("AWS Secrets Manager provider vault is disabled");
140
+ }
141
+ if (input.status === "coming_soon") {
142
+ throw unprocessable("AWS Secrets Manager provider vault runtime is locked while coming soon");
143
+ }
144
+ const region = asOptionalNonEmptyString(input.config.region);
145
+ if (!region) {
146
+ throw unprocessable("AWS Secrets Manager provider vault requires non-secret config: region");
147
+ }
148
+ const recoveryWindowRaw = process.env.PAPERCLIP_SECRETS_AWS_DELETE_RECOVERY_DAYS?.trim();
149
+ const recoveryWindow = recoveryWindowRaw ? Number(recoveryWindowRaw) : DEFAULT_DELETE_RECOVERY_WINDOW_DAYS;
150
+ if (!Number.isFinite(recoveryWindow) || recoveryWindow < 7 || recoveryWindow > 30) {
151
+ throw unprocessable("PAPERCLIP_SECRETS_AWS_DELETE_RECOVERY_DAYS must be an integer between 7 and 30");
152
+ }
153
+ return {
154
+ region,
155
+ endpoint: process.env.PAPERCLIP_SECRETS_AWS_ENDPOINT?.trim() ||
156
+ `https://secretsmanager.${region}.amazonaws.com`,
157
+ deploymentId: sanitizePathSegment(asOptionalNonEmptyString(input.config.namespace) ?? input.id),
158
+ prefix: sanitizePathSegment(asOptionalNonEmptyString(input.config.secretNamePrefix) || DEFAULT_PREFIX),
159
+ kmsKeyId: asOptionalNonEmptyString(input.config.kmsKeyId),
160
+ environmentTag: asOptionalNonEmptyString(input.config.environmentTag) ||
161
+ process.env.NODE_ENV?.trim() ||
162
+ "unknown",
163
+ providerOwnerTag: asOptionalNonEmptyString(input.config.ownerTag) || DEFAULT_OWNER_TAG,
164
+ deleteRecoveryWindowDays: recoveryWindow,
165
+ };
166
+ }
167
+ function getAwsConfigReadiness() {
168
+ const region = (process.env.PAPERCLIP_SECRETS_AWS_REGION ??
169
+ process.env.AWS_REGION ??
170
+ process.env.AWS_DEFAULT_REGION)?.trim();
171
+ const deploymentId = process.env.PAPERCLIP_SECRETS_AWS_DEPLOYMENT_ID?.trim();
172
+ const kmsKeyId = process.env.PAPERCLIP_SECRETS_AWS_KMS_KEY_ID?.trim();
173
+ const missingConfig = [];
174
+ if (!region) {
175
+ missingConfig.push("PAPERCLIP_SECRETS_AWS_REGION or AWS_REGION/AWS_DEFAULT_REGION");
176
+ }
177
+ if (!deploymentId) {
178
+ missingConfig.push("PAPERCLIP_SECRETS_AWS_DEPLOYMENT_ID");
179
+ }
180
+ if (!kmsKeyId) {
181
+ missingConfig.push("PAPERCLIP_SECRETS_AWS_KMS_KEY_ID");
182
+ }
183
+ return {
184
+ missingConfig,
185
+ region: region || null,
186
+ deploymentId: deploymentId || null,
187
+ kmsKeyConfigured: Boolean(kmsKeyId),
188
+ credentialSources: describeDetectedAwsCredentialSources(),
189
+ };
190
+ }
191
+ function describeDetectedAwsCredentialSources() {
192
+ const sources = [];
193
+ if (process.env.AWS_PROFILE?.trim())
194
+ sources.push("AWS_PROFILE/shared config");
195
+ if (process.env.AWS_ACCESS_KEY_ID?.trim() && process.env.AWS_SECRET_ACCESS_KEY?.trim()) {
196
+ sources.push("temporary AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY environment credentials");
197
+ }
198
+ if (process.env.AWS_WEB_IDENTITY_TOKEN_FILE?.trim() && process.env.AWS_ROLE_ARN?.trim()) {
199
+ sources.push("AWS web identity token");
200
+ }
201
+ if (process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI?.trim() ||
202
+ process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI?.trim()) {
203
+ sources.push("AWS container credentials endpoint");
204
+ }
205
+ if (process.env.AWS_SHARED_CREDENTIALS_FILE?.trim() || process.env.AWS_CONFIG_FILE?.trim()) {
206
+ sources.push("custom AWS shared credentials/config file");
207
+ }
208
+ return sources;
209
+ }
210
+ function loadAwsSecretsManagerConfig() {
211
+ const readiness = getAwsConfigReadiness();
212
+ const region = process.env.PAPERCLIP_SECRETS_AWS_REGION?.trim() ||
213
+ process.env.AWS_REGION?.trim() ||
214
+ process.env.AWS_DEFAULT_REGION?.trim();
215
+ const deploymentId = process.env.PAPERCLIP_SECRETS_AWS_DEPLOYMENT_ID?.trim();
216
+ const kmsKeyId = process.env.PAPERCLIP_SECRETS_AWS_KMS_KEY_ID?.trim();
217
+ if (readiness.missingConfig.length > 0) {
218
+ throw unprocessable(`AWS Secrets Manager provider requires non-secret config: ${readiness.missingConfig.join(", ")}`);
219
+ }
220
+ if (!region) {
221
+ throw unprocessable("AWS Secrets Manager provider requires PAPERCLIP_SECRETS_AWS_REGION or AWS_REGION");
222
+ }
223
+ if (!deploymentId) {
224
+ throw unprocessable("AWS Secrets Manager provider requires PAPERCLIP_SECRETS_AWS_DEPLOYMENT_ID");
225
+ }
226
+ if (!kmsKeyId) {
227
+ throw unprocessable("AWS Secrets Manager provider requires PAPERCLIP_SECRETS_AWS_KMS_KEY_ID");
228
+ }
229
+ const recoveryWindowRaw = process.env.PAPERCLIP_SECRETS_AWS_DELETE_RECOVERY_DAYS?.trim();
230
+ const recoveryWindow = recoveryWindowRaw ? Number(recoveryWindowRaw) : DEFAULT_DELETE_RECOVERY_WINDOW_DAYS;
231
+ if (!Number.isFinite(recoveryWindow) || recoveryWindow < 7 || recoveryWindow > 30) {
232
+ throw unprocessable("PAPERCLIP_SECRETS_AWS_DELETE_RECOVERY_DAYS must be an integer between 7 and 30");
233
+ }
234
+ return {
235
+ region,
236
+ endpoint: process.env.PAPERCLIP_SECRETS_AWS_ENDPOINT?.trim() ||
237
+ `https://secretsmanager.${region}.amazonaws.com`,
238
+ deploymentId,
239
+ prefix: sanitizePathSegment(process.env.PAPERCLIP_SECRETS_AWS_PREFIX?.trim() || DEFAULT_PREFIX),
240
+ kmsKeyId,
241
+ environmentTag: process.env.PAPERCLIP_SECRETS_AWS_ENVIRONMENT?.trim() ||
242
+ process.env.NODE_ENV?.trim() ||
243
+ "unknown",
244
+ providerOwnerTag: process.env.PAPERCLIP_SECRETS_AWS_PROVIDER_OWNER?.trim() || DEFAULT_OWNER_TAG,
245
+ deleteRecoveryWindowDays: recoveryWindow,
246
+ };
247
+ }
248
+ function sanitizePathSegment(input) {
249
+ return input
250
+ .trim()
251
+ .replace(/[^A-Za-z0-9/_+=.@-]+/g, "-")
252
+ .replace(/\/+/g, "/")
253
+ .replace(/^\/+|\/+$/g, "");
254
+ }
255
+ function buildManagedSecretName(config, context) {
256
+ if (!context) {
257
+ throw unprocessable("AWS Secrets Manager provider requires secret context for managed values");
258
+ }
259
+ return [
260
+ sanitizePathSegment(config.prefix),
261
+ sanitizePathSegment(config.deploymentId),
262
+ sanitizePathSegment(context.companyId),
263
+ sanitizePathSegment(context.secretKey),
264
+ ]
265
+ .filter(Boolean)
266
+ .join("/");
267
+ }
268
+ function buildManagedSecretId(config, context) {
269
+ return buildManagedSecretName(config, context);
270
+ }
271
+ function escapeRegExp(value) {
272
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
273
+ }
274
+ function extractAwsSecretName(externalRef) {
275
+ const trimmed = externalRef.trim();
276
+ const arnMatch = /^arn:[^:]+:secretsmanager:[^:]*:[^:]*:secret:(.+)$/i.exec(trimmed);
277
+ return arnMatch?.[1] ?? trimmed;
278
+ }
279
+ function isManagedSecretRefForContext(config, context, externalRef) {
280
+ if (!externalRef?.trim())
281
+ return false;
282
+ const expectedName = buildManagedSecretName(config, context);
283
+ const actualName = extractAwsSecretName(externalRef);
284
+ return new RegExp(`^${escapeRegExp(expectedName)}(?:-[A-Za-z0-9]{6})?$`).test(actualName);
285
+ }
286
+ function isManagedSecretNamespaceRef(config, externalRef) {
287
+ if (!externalRef?.trim())
288
+ return false;
289
+ const namespacePrefix = [
290
+ sanitizePathSegment(config.prefix),
291
+ sanitizePathSegment(config.deploymentId),
292
+ ]
293
+ .filter(Boolean)
294
+ .join("/");
295
+ if (!namespacePrefix)
296
+ return false;
297
+ const actualName = extractAwsSecretName(externalRef);
298
+ return actualName === namespacePrefix || actualName.startsWith(`${namespacePrefix}/`);
299
+ }
300
+ function assertNotManagedNamespaceExternalRef(config, externalRef) {
301
+ if (!isManagedSecretNamespaceRef(config, externalRef))
302
+ return;
303
+ throw unprocessable("AWS Paperclip-managed namespace secrets cannot be imported as external references");
304
+ }
305
+ function resolveManagedSecretRef(input) {
306
+ let sawNonEmptyExternalRef = false;
307
+ for (const externalRef of input.externalRefs) {
308
+ if (externalRef?.trim()) {
309
+ sawNonEmptyExternalRef = true;
310
+ }
311
+ if (externalRef?.trim() && isManagedSecretRefForContext(input.config, input.context, externalRef)) {
312
+ return externalRef.trim();
313
+ }
314
+ }
315
+ if (sawNonEmptyExternalRef) {
316
+ throw unprocessable("AWS Secrets Manager managed secret ref drifted outside the derived deployment/company scope");
317
+ }
318
+ return buildManagedSecretId(input.config, input.context);
319
+ }
320
+ function buildManagedSecretTags(config, context) {
321
+ if (!context)
322
+ return [];
323
+ return [
324
+ { Key: "paperclip:managed-by", Value: "paperclip" },
325
+ { Key: "paperclip:provider-owner", Value: config.providerOwnerTag },
326
+ { Key: "paperclip:deployment-id", Value: config.deploymentId },
327
+ { Key: "paperclip:company-id", Value: context.companyId },
328
+ { Key: "paperclip:secret-key", Value: context.secretKey },
329
+ { Key: "paperclip:environment", Value: config.environmentTag },
330
+ ];
331
+ }
332
+ function createExternalReferenceMaterial(externalRef, providerVersionRef) {
333
+ const normalizedExternalRef = externalRef.trim();
334
+ const normalizedProviderVersionRef = providerVersionRef?.trim() || null;
335
+ const fingerprint = sha256Hex(`${AWS_SECRETS_MANAGER_SCHEME}:${normalizedExternalRef}:${normalizedProviderVersionRef ?? ""}`);
336
+ return {
337
+ material: {
338
+ scheme: AWS_SECRETS_MANAGER_SCHEME,
339
+ secretId: normalizedExternalRef,
340
+ versionId: normalizedProviderVersionRef,
341
+ source: "external_reference",
342
+ },
343
+ valueSha256: fingerprint,
344
+ fingerprintSha256: fingerprint,
345
+ externalRef: normalizedExternalRef,
346
+ providerVersionRef: normalizedProviderVersionRef,
347
+ };
348
+ }
349
+ function createManagedMaterial(secretId, versionId) {
350
+ return {
351
+ scheme: AWS_SECRETS_MANAGER_SCHEME,
352
+ secretId,
353
+ versionId,
354
+ source: "managed",
355
+ };
356
+ }
357
+ function serializeAwsDate(value) {
358
+ if (value === undefined)
359
+ return null;
360
+ const date = value instanceof Date ? value : new Date(value);
361
+ return Number.isNaN(date.getTime()) ? null : date.toISOString();
362
+ }
363
+ function createRemoteSecretMetadata(entry) {
364
+ return {
365
+ createdDate: serializeAwsDate(entry.CreatedDate),
366
+ lastAccessedDate: serializeAwsDate(entry.LastAccessedDate),
367
+ lastChangedDate: serializeAwsDate(entry.LastChangedDate),
368
+ deletedDate: serializeAwsDate(entry.DeletedDate),
369
+ hasDescription: Boolean(entry.Description),
370
+ hasKmsKey: Boolean(entry.KmsKeyId),
371
+ tagCount: Array.isArray(entry.Tags) ? entry.Tags.length : 0,
372
+ };
373
+ }
374
+ function asAwsSecretsManagerMaterial(value) {
375
+ if (value &&
376
+ typeof value === "object" &&
377
+ value.scheme === AWS_SECRETS_MANAGER_SCHEME &&
378
+ typeof value.secretId === "string" &&
379
+ (typeof value.versionId === "string" || value.versionId === null) &&
380
+ (value.source === "managed" || value.source === "external_reference")) {
381
+ return value;
382
+ }
383
+ throw unprocessable("Invalid AWS Secrets Manager material");
384
+ }
385
+ function classifyAwsProviderError(message) {
386
+ if (/ResourceExistsException|AlreadyExists/i.test(message))
387
+ return "conflict";
388
+ if (/ResourceNotFoundException|NotFound/i.test(message))
389
+ return "not_found";
390
+ if (/AccessDeniedException|AccessDenied|UnrecognizedClientException|InvalidClientTokenId|not authorized/i.test(message)) {
391
+ return "access_denied";
392
+ }
393
+ if (/Throttl|TooManyRequests|RequestLimitExceeded|Rate exceeded/i.test(message))
394
+ return "throttled";
395
+ if (/ValidationException|InvalidParameter|InvalidRequest/i.test(message))
396
+ return "invalid_request";
397
+ if (/fetch failed|ECONN|ENOTFOUND|ETIMEDOUT|network|timeout/i.test(message))
398
+ return "provider_unavailable";
399
+ return "provider_error";
400
+ }
401
+ function awsProviderSafeMessage(code) {
402
+ switch (code) {
403
+ case "access_denied":
404
+ return "AWS Secrets Manager denied the request. Check IAM permissions for this provider vault.";
405
+ case "throttled":
406
+ return "AWS Secrets Manager throttled the request. Wait and try again.";
407
+ case "not_found":
408
+ return "AWS Secrets Manager could not find the requested secret.";
409
+ case "conflict":
410
+ return "AWS Secrets Manager reported that the requested secret already exists.";
411
+ case "invalid_request":
412
+ return "AWS Secrets Manager rejected the request.";
413
+ case "provider_unavailable":
414
+ return "AWS Secrets Manager is unavailable right now.";
415
+ case "provider_error":
416
+ default:
417
+ return "AWS Secrets Manager request failed.";
418
+ }
419
+ }
420
+ function normalizeAwsError(operation, error) {
421
+ const rawMessage = error instanceof Error ? error.message : String(error);
422
+ const code = classifyAwsProviderError(rawMessage);
423
+ throw new SecretProviderClientError({
424
+ code,
425
+ provider: "aws_secrets_manager",
426
+ operation,
427
+ message: awsProviderSafeMessage(code),
428
+ rawMessage,
429
+ cause: error,
430
+ });
431
+ }
432
+ class AwsSecretsManagerJsonGateway {
433
+ config;
434
+ endpoint;
435
+ constructor(config) {
436
+ this.config = config;
437
+ this.endpoint = new URL(config.endpoint);
438
+ }
439
+ createSecret(input) {
440
+ return this.call("CreateSecret", input);
441
+ }
442
+ putSecretValue(input) {
443
+ return this.call("PutSecretValue", input);
444
+ }
445
+ getSecretValue(input) {
446
+ return this.call("GetSecretValue", input);
447
+ }
448
+ deleteSecret(input) {
449
+ return this.call("DeleteSecret", input);
450
+ }
451
+ updateSecretVersionStage(input) {
452
+ return this.call("UpdateSecretVersionStage", input);
453
+ }
454
+ listSecrets(input) {
455
+ return this.call("ListSecrets", input);
456
+ }
457
+ async call(operation, payload) {
458
+ const body = JSON.stringify(payload);
459
+ const credentials = await loadAwsCredentials(this.config.region);
460
+ const headers = signAwsSecretsManagerRequest({
461
+ endpoint: this.endpoint,
462
+ region: this.config.region,
463
+ operation,
464
+ body,
465
+ credentials,
466
+ });
467
+ const response = await fetch(this.endpoint, {
468
+ method: "POST",
469
+ headers,
470
+ body,
471
+ signal: AbortSignal.timeout(AWS_SECRETS_MANAGER_REQUEST_TIMEOUT_MS),
472
+ });
473
+ const text = await response.text();
474
+ const parsed = text ? JSON.parse(text) : {};
475
+ if (!response.ok) {
476
+ const code = String(parsed.__type ?? parsed.code ?? parsed.Code ?? response.statusText ?? "UnknownError");
477
+ const message = String(parsed.message ?? parsed.Message ?? code);
478
+ const rawMessage = `${code}: ${message}`;
479
+ const clientCode = classifyAwsProviderError(rawMessage);
480
+ throw new SecretProviderClientError({
481
+ code: clientCode,
482
+ provider: "aws_secrets_manager",
483
+ operation,
484
+ message: awsProviderSafeMessage(clientCode),
485
+ rawMessage,
486
+ });
487
+ }
488
+ return parsed;
489
+ }
490
+ }
491
+ export function createAwsSecretsManagerProvider(options) {
492
+ function resolveConfig(providerConfig) {
493
+ if (providerConfig)
494
+ return readProviderVaultConfig(providerConfig);
495
+ return options?.config ?? loadAwsSecretsManagerConfig();
496
+ }
497
+ function resolveGateway(config) {
498
+ return options?.gateway ?? new AwsSecretsManagerJsonGateway(config);
499
+ }
500
+ async function validateConfig(input) {
501
+ const warnings = [];
502
+ if (input?.deploymentMode === "authenticated" && input.strictMode !== true) {
503
+ warnings.push("Strict secret mode should be enabled for authenticated deployments");
504
+ }
505
+ const config = resolveConfig(input?.providerConfig);
506
+ if (!config.prefix) {
507
+ warnings.push("PAPERCLIP_SECRETS_AWS_PREFIX should be set to a deployment-scoped prefix");
508
+ }
509
+ return { ok: true, warnings };
510
+ }
511
+ async function healthCheck(input) {
512
+ try {
513
+ const validation = await validateConfig(input);
514
+ const config = resolveConfig(input?.providerConfig);
515
+ const readiness = getAwsConfigReadiness();
516
+ const warnings = [...validation.warnings];
517
+ if (process.env.AWS_ACCESS_KEY_ID?.trim() &&
518
+ process.env.AWS_SECRET_ACCESS_KEY?.trim()) {
519
+ warnings.push("AWS static environment credentials are visible to this process; use only short-lived shell credentials locally and prefer IAM role/workload identity for hosted deployments.");
520
+ }
521
+ return {
522
+ provider: "aws_secrets_manager",
523
+ status: warnings.length > 0 ? "warn" : "ok",
524
+ message: "AWS Secrets Manager provider config is present; AWS credentials are resolved by the server runtime through the AWS SDK default credential provider chain.",
525
+ warnings,
526
+ details: {
527
+ region: config.region,
528
+ prefix: config.prefix,
529
+ deploymentId: config.deploymentId,
530
+ kmsKeyConfigured: Boolean(config.kmsKeyId),
531
+ credentialSource: "AWS SDK default credential provider chain",
532
+ detectedCredentialSources: readiness.credentialSources,
533
+ },
534
+ backupGuidance: [
535
+ "Back up Paperclip metadata separately from AWS-managed secrets.",
536
+ "Restoring access requires the Paperclip database plus the same AWS secret namespace and KMS permissions.",
537
+ ],
538
+ };
539
+ }
540
+ catch (error) {
541
+ const readiness = getAwsConfigReadiness();
542
+ const providerConfigMissing = input?.providerConfig && !asOptionalNonEmptyString(input.providerConfig.config.region)
543
+ ? ["region"]
544
+ : [];
545
+ const missingConfig = input?.providerConfig ? providerConfigMissing : readiness.missingConfig;
546
+ return {
547
+ provider: "aws_secrets_manager",
548
+ status: "warn",
549
+ message: missingConfig.length > 0
550
+ ? `AWS Secrets Manager provider is not ready: missing ${missingConfig.join(", ")}.`
551
+ : error instanceof Error
552
+ ? error.message
553
+ : String(error),
554
+ warnings: [
555
+ ...(missingConfig.length > 0
556
+ ? [`Missing required non-secret AWS provider config: ${missingConfig.join(", ")}.`]
557
+ : []),
558
+ AWS_RUNTIME_CREDENTIAL_WARNING,
559
+ AWS_CREDENTIAL_CUSTODY_WARNING,
560
+ "Managed secret create/rotate/resolve calls will fail until AWS provider configuration is complete.",
561
+ ],
562
+ details: {
563
+ missingConfig,
564
+ requiredProviderConfig: input?.providerConfig
565
+ ? ["region"]
566
+ : [
567
+ "PAPERCLIP_SECRETS_AWS_REGION or AWS_REGION/AWS_DEFAULT_REGION",
568
+ "PAPERCLIP_SECRETS_AWS_DEPLOYMENT_ID",
569
+ "PAPERCLIP_SECRETS_AWS_KMS_KEY_ID",
570
+ ],
571
+ optionalProviderConfig: [
572
+ "PAPERCLIP_SECRETS_AWS_PREFIX",
573
+ "PAPERCLIP_SECRETS_AWS_ENVIRONMENT",
574
+ "PAPERCLIP_SECRETS_AWS_PROVIDER_OWNER",
575
+ "PAPERCLIP_SECRETS_AWS_ENDPOINT",
576
+ "PAPERCLIP_SECRETS_AWS_DELETE_RECOVERY_DAYS",
577
+ ],
578
+ credentialSource: "AWS SDK default credential provider chain",
579
+ detectedCredentialSources: readiness.credentialSources,
580
+ },
581
+ };
582
+ }
583
+ }
584
+ return {
585
+ id: "aws_secrets_manager",
586
+ descriptor() {
587
+ return configuredAwsSecretsManagerDescriptor();
588
+ },
589
+ validateConfig,
590
+ async createSecret(input) {
591
+ const config = resolveConfig(input.providerConfig);
592
+ const gateway = resolveGateway(config);
593
+ const valueSha256 = sha256Hex(input.value);
594
+ const secretId = buildManagedSecretId(config, input.context);
595
+ try {
596
+ const createInput = {
597
+ Name: secretId,
598
+ SecretString: input.value,
599
+ ...(config.kmsKeyId ? { KmsKeyId: config.kmsKeyId } : {}),
600
+ Description: input.context ? `Paperclip secret ${input.context.secretName}` : undefined,
601
+ Tags: buildManagedSecretTags(config, input.context),
602
+ };
603
+ const created = await gateway.createSecret({
604
+ ...createInput,
605
+ });
606
+ const normalizedSecretId = created.ARN ?? created.Name ?? secretId;
607
+ return {
608
+ material: createManagedMaterial(normalizedSecretId, created.VersionId ?? null),
609
+ valueSha256,
610
+ fingerprintSha256: valueSha256,
611
+ externalRef: normalizedSecretId,
612
+ providerVersionRef: created.VersionId ?? null,
613
+ };
614
+ }
615
+ catch (error) {
616
+ normalizeAwsError("createSecret", error);
617
+ }
618
+ },
619
+ async createVersion(input) {
620
+ const config = resolveConfig(input.providerConfig);
621
+ const gateway = resolveGateway(config);
622
+ const valueSha256 = sha256Hex(input.value);
623
+ const secretId = resolveManagedSecretRef({
624
+ config,
625
+ context: input.context,
626
+ externalRefs: [input.externalRef],
627
+ });
628
+ try {
629
+ const created = await gateway.putSecretValue({
630
+ SecretId: secretId,
631
+ SecretString: input.value,
632
+ VersionStages: [PAPERCLIP_PENDING_VERSION_STAGE],
633
+ });
634
+ const normalizedSecretId = created.ARN ?? created.Name ?? secretId;
635
+ return {
636
+ material: createManagedMaterial(normalizedSecretId, created.VersionId ?? null),
637
+ valueSha256,
638
+ fingerprintSha256: valueSha256,
639
+ externalRef: normalizedSecretId,
640
+ providerVersionRef: created.VersionId ?? null,
641
+ };
642
+ }
643
+ catch (error) {
644
+ normalizeAwsError("createVersion", error);
645
+ }
646
+ },
647
+ async linkExternalSecret(input) {
648
+ const config = resolveConfig(input.providerConfig);
649
+ assertNotManagedNamespaceExternalRef(config, input.externalRef);
650
+ return createExternalReferenceMaterial(input.externalRef, input.providerVersionRef ?? null);
651
+ },
652
+ async listRemoteSecrets(input) {
653
+ const config = resolveConfig(input.providerConfig);
654
+ const gateway = resolveGateway(config);
655
+ const query = input.query?.trim();
656
+ const pageSize = input.pageSize && Number.isFinite(input.pageSize)
657
+ ? Math.min(Math.max(Math.trunc(input.pageSize), 1), 100)
658
+ : 50;
659
+ try {
660
+ if (!gateway.listSecrets) {
661
+ throw new Error("ListSecrets gateway operation is unavailable");
662
+ }
663
+ const listed = await gateway.listSecrets({
664
+ MaxResults: pageSize,
665
+ NextToken: input.nextToken?.trim() || undefined,
666
+ IncludePlannedDeletion: false,
667
+ Filters: query ? [{ Key: "all", Values: [query] }] : undefined,
668
+ });
669
+ return {
670
+ nextToken: listed.NextToken ?? null,
671
+ secrets: (listed.SecretList ?? [])
672
+ .filter((entry) => Boolean(entry.ARN ?? entry.Name))
673
+ .map((entry) => ({
674
+ externalRef: entry.ARN ?? entry.Name ?? "",
675
+ name: entry.Name ?? entry.ARN ?? "",
676
+ providerVersionRef: null,
677
+ metadata: createRemoteSecretMetadata(entry),
678
+ })),
679
+ };
680
+ }
681
+ catch (error) {
682
+ normalizeAwsError("listSecrets", error);
683
+ }
684
+ },
685
+ async resolveVersion(input) {
686
+ const config = resolveConfig(input.providerConfig);
687
+ const gateway = resolveGateway(config);
688
+ const material = asAwsSecretsManagerMaterial(input.material);
689
+ const secretId = material.source === "managed"
690
+ ? resolveManagedSecretRef({
691
+ config,
692
+ context: input.context,
693
+ externalRefs: [input.externalRef, material.secretId],
694
+ })
695
+ : (input.externalRef ?? material.secretId);
696
+ try {
697
+ const resolved = await gateway.getSecretValue({
698
+ SecretId: secretId,
699
+ VersionId: input.providerVersionRef ?? material.versionId ?? undefined,
700
+ VersionStage: input.providerVersionRef || material.versionId ? undefined : DEFAULT_VERSION_STAGE,
701
+ });
702
+ if (typeof resolved.SecretString !== "string") {
703
+ throw new Error("SecretString was empty");
704
+ }
705
+ return resolved.SecretString;
706
+ }
707
+ catch (error) {
708
+ normalizeAwsError("resolveVersion", error);
709
+ }
710
+ },
711
+ async deleteOrArchive(input) {
712
+ const material = input.material && typeof input.material === "object"
713
+ ? asAwsSecretsManagerMaterial(input.material)
714
+ : null;
715
+ if (material?.source !== "managed")
716
+ return;
717
+ const config = resolveConfig(input.providerConfig);
718
+ const gateway = resolveGateway(config);
719
+ const secretId = resolveManagedSecretRef({
720
+ config,
721
+ context: input.context,
722
+ externalRefs: [input.externalRef, material.secretId],
723
+ });
724
+ try {
725
+ if (input.mode === "archive") {
726
+ if (material.versionId && gateway.updateSecretVersionStage) {
727
+ await gateway.updateSecretVersionStage({
728
+ SecretId: secretId,
729
+ VersionStage: PAPERCLIP_PENDING_VERSION_STAGE,
730
+ RemoveFromVersionId: material.versionId,
731
+ });
732
+ }
733
+ return;
734
+ }
735
+ await gateway.deleteSecret({
736
+ SecretId: secretId,
737
+ RecoveryWindowInDays: config.deleteRecoveryWindowDays,
738
+ });
739
+ }
740
+ catch (error) {
741
+ normalizeAwsError(input.mode === "archive" ? "updateSecretVersionStage" : "deleteSecret", error);
742
+ }
743
+ },
744
+ healthCheck,
745
+ };
746
+ }
747
+ export const awsSecretsManagerProvider = createAwsSecretsManagerProvider();
748
+ //# sourceMappingURL=aws-secrets-manager-provider.js.map