@flipboxlabs/aws-audit-sdk 1.1.0 → 1.1.2

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @flipboxlabs/aws-audit-sdk
2
2
 
3
- AWS Audit SDK - Core SDK for audit logging and event management.
3
+ AWS Audit SDK - Core SDK for batch audit logging and event management
4
4
 
5
5
  ## Installation
6
6
 
@@ -14,10 +14,6 @@
14
14
  * ```
15
15
  */
16
16
  export declare const AUDIT_LOG_IDENTIFIER = "_audit";
17
- /**
18
- * SDK version string for debugging and compatibility checks.
19
- */
20
- export declare const SDK_VERSION = "1.0.0";
21
17
  /**
22
18
  * Configuration for generating resource names.
23
19
  */
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAE7C;;GAEG;AACH,eAAO,MAAM,WAAW,UAAU,CAAC;AAEnC;;GAEG;AACH,KAAK,UAAU,GAAG;IACjB,wDAAwD;IACxD,GAAG,EAAE,MAAM,CAAC;IAEZ,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;GAGG;AACH,KAAK,SAAS,GAAG,UAAU,GAAG;IAC7B,yCAAyC;IACzC,GAAG,EAAE;QACJ,qCAAqC;QACrC,MAAM,EAAE,MAAM,CAAC;QACf,qBAAqB;QACrB,OAAO,EAAE,MAAM,CAAC;KAChB,CAAC;CACF,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,QAAQ;IACpB,oCAAoC;;QAEnC,6DAA6D;iCAC7C,UAAU;QAC1B,4CAA4C;gCAC7B,SAAS;;IAEzB,mCAAmC;;QAElC,4BAA4B;;QAE5B,uBAAuB;;QAGvB,yCAAyC;;QAEzC,oCAAoC;;QAGpC,yCAAyC;;QAEzC,oCAAoC;;QAGpC,6BAA6B;;QAE7B,8BAA8B;;;IAG/B,4BAA4B;;QAE3B,+DAA+D;;QAE/D,gEAAgE;;QAGhE,gDAAgD;;QAEhD,iDAAiD;;;IAGlD,8BAA8B;;QAE7B,2DAA2D;;;CAGnD,CAAC;AA4CX;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,WAAW;IACvB,wCAAwC;;QAEvC,8DAA8D;iCAC9C,UAAU;QAC1B,6CAA6C;gCAC9B,SAAS;;IAEzB,yCAAyC;;IAEzC,wDAAwD;;QAEvD,yDAAyD;;QAEzD,8CAA8C;;;CAGtC,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,wBAAwB,GACnC,CAAC,OAAO,WAAW,CAAC,UAAU,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,UAAU,CAAC,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAE7C;;GAEG;AACH,KAAK,UAAU,GAAG;IACjB,wDAAwD;IACxD,GAAG,EAAE,MAAM,CAAC;IAEZ,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;GAGG;AACH,KAAK,SAAS,GAAG,UAAU,GAAG;IAC7B,yCAAyC;IACzC,GAAG,EAAE;QACJ,qCAAqC;QACrC,MAAM,EAAE,MAAM,CAAC;QACf,qBAAqB;QACrB,OAAO,EAAE,MAAM,CAAC;KAChB,CAAC;CACF,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,QAAQ;IACpB,oCAAoC;;QAEnC,6DAA6D;iCAC7C,UAAU;QAC1B,4CAA4C;gCAC7B,SAAS;;IAEzB,mCAAmC;;QAElC,4BAA4B;;QAE5B,uBAAuB;;QAGvB,yCAAyC;;QAEzC,oCAAoC;;QAGpC,yCAAyC;;QAEzC,oCAAoC;;QAGpC,6BAA6B;;QAE7B,8BAA8B;;;IAG/B,4BAA4B;;QAE3B,+DAA+D;;QAE/D,gEAAgE;;QAGhE,gDAAgD;;QAEhD,iDAAiD;;;IAGlD,8BAA8B;;QAE7B,2DAA2D;;;CAGnD,CAAC;AA4CX;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,WAAW;IACvB,wCAAwC;;QAEvC,8DAA8D;iCAC9C,UAAU;QAC1B,6CAA6C;gCAC9B,SAAS;;IAEzB,yCAAyC;;IAEzC,wDAAwD;;QAEvD,yDAAyD;;QAEzD,8CAA8C;;;CAGtC,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,wBAAwB,GACnC,CAAC,OAAO,WAAW,CAAC,UAAU,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,UAAU,CAAC,CAAC"}
package/dist/constants.js CHANGED
@@ -14,10 +14,6 @@
14
14
  * ```
15
15
  */
16
16
  export const AUDIT_LOG_IDENTIFIER = "_audit";
17
- /**
18
- * SDK version string for debugging and compatibility checks.
19
- */
20
- export const SDK_VERSION = "1.0.0";
21
17
  /**
22
18
  * DynamoDB configuration constants for the audit table.
23
19
  *
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export * from "./audits.js";
2
2
  export * from "./config.js";
3
- export { type AnyEventBridgeDetailType, AUDIT_LOG_IDENTIFIER, DynamoDB, EventBridge, SDK_VERSION, } from "./constants.js";
3
+ export { type AnyEventBridgeDetailType, AUDIT_LOG_IDENTIFIER, DynamoDB, EventBridge, } from "./constants.js";
4
4
  export * from "./events/index.js";
5
5
  export * from "./schema/index.js";
6
6
  export * from "./service.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,OAAO,EACN,KAAK,wBAAwB,EAC7B,oBAAoB,EACpB,QAAQ,EACR,WAAW,EACX,WAAW,GACX,MAAM,gBAAgB,CAAC;AACxB,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,OAAO,EACN,UAAU,EACV,uBAAuB,EACvB,eAAe,EACf,WAAW,EACX,OAAO,EACP,0BAA0B,GAC1B,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,OAAO,EACN,KAAK,wBAAwB,EAC7B,oBAAoB,EACpB,QAAQ,EACR,WAAW,GACX,MAAM,gBAAgB,CAAC;AACxB,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,OAAO,EACN,UAAU,EACV,uBAAuB,EACvB,eAAe,EACf,WAAW,EACX,OAAO,EACP,0BAA0B,GAC1B,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export * from "./audits.js";
2
2
  export * from "./config.js";
3
- export { AUDIT_LOG_IDENTIFIER, DynamoDB, EventBridge, SDK_VERSION, } from "./constants.js";
3
+ export { AUDIT_LOG_IDENTIFIER, DynamoDB, EventBridge, } from "./constants.js";
4
4
  export * from "./events/index.js";
5
5
  export * from "./schema/index.js";
6
6
  export * from "./service.js";
@@ -197,6 +197,34 @@ export declare class AuditRepository<C extends AuditConfig> {
197
197
  * ```
198
198
  */
199
199
  upsertBatch(items: Array<UpsertAuditInput>): Promise<boolean>;
200
+ /**
201
+ * Upserts a single audit record with atomic attempt tracking.
202
+ *
203
+ * Uses DynamoDB UpdateItem with conditional expressions to:
204
+ * - Create a new item if it doesn't exist (with attempts = [currentAttempt])
205
+ * - Append to existing attempts array if item exists
206
+ * - Preserve original createdAt timestamp on updates
207
+ *
208
+ * This is atomic and race-condition safe for retry tracking.
209
+ *
210
+ * @param item - The audit record to upsert
211
+ * @param currentAttempt - The current attempt to append
212
+ * @returns The attempt number (1 for new items, incremented for existing)
213
+ *
214
+ * @example
215
+ * ```typescript
216
+ * const attemptNumber = await repository.upsertItem(
217
+ * { operation: 'processPayment', status: 'success', ... },
218
+ * { number: 1, status: 'success', at: '2024-01-01T00:00:00Z' }
219
+ * );
220
+ * ```
221
+ */
222
+ upsertItem(item: UpsertAuditInput, currentAttempt: {
223
+ number: number;
224
+ status: string;
225
+ error?: unknown;
226
+ at: string;
227
+ }): Promise<number>;
200
228
  /**
201
229
  * Lists audit records for a specific resource with pagination.
202
230
  *
@@ -1 +1 @@
1
- {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { BatchWriteItemCommand, DynamoDBClient, GetItemCommand, QueryCommand, } from "@aws-sdk/client-dynamodb";
1
+ import { BatchWriteItemCommand, DynamoDBClient, GetItemCommand, QueryCommand, UpdateItemCommand, } from "@aws-sdk/client-dynamodb";
2
2
  import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";
3
3
  import { DynamoDB } from "./constants.js";
4
4
  import { decodeNextPageToken, encodeNextPageToken, } from "./repository.utils.js";
@@ -189,6 +189,93 @@ export class AuditRepository {
189
189
  }))));
190
190
  return true;
191
191
  }
192
+ /**
193
+ * Upserts a single audit record with atomic attempt tracking.
194
+ *
195
+ * Uses DynamoDB UpdateItem with conditional expressions to:
196
+ * - Create a new item if it doesn't exist (with attempts = [currentAttempt])
197
+ * - Append to existing attempts array if item exists
198
+ * - Preserve original createdAt timestamp on updates
199
+ *
200
+ * This is atomic and race-condition safe for retry tracking.
201
+ *
202
+ * @param item - The audit record to upsert
203
+ * @param currentAttempt - The current attempt to append
204
+ * @returns The attempt number (1 for new items, incremented for existing)
205
+ *
206
+ * @example
207
+ * ```typescript
208
+ * const attemptNumber = await repository.upsertItem(
209
+ * { operation: 'processPayment', status: 'success', ... },
210
+ * { number: 1, status: 'success', at: '2024-01-01T00:00:00Z' }
211
+ * );
212
+ * ```
213
+ */
214
+ async upsertItem(item, currentAttempt) {
215
+ const now = new Date();
216
+ const payload = AuditStorageSchema.parse({
217
+ createdAt: now,
218
+ ...item,
219
+ updatedAt: now,
220
+ });
221
+ const primaryKey = this.constructPrimaryKey({
222
+ tenantId: payload.tenantId,
223
+ id: payload.id,
224
+ resourceType: payload.target.type,
225
+ app: payload.target.app,
226
+ });
227
+ const secondaryKeys = this.constructSecondaryKeys(payload);
228
+ const ttlAttribute = this.constructTTLAttribute(DEFAULT_TTL);
229
+ const expressionAttributeNames = {};
230
+ const expressionAttributeValues = {
231
+ ":emptyList": [],
232
+ ":newAttempt": [currentAttempt],
233
+ };
234
+ const setClauses = [
235
+ "#attempts = list_append(if_not_exists(#attempts, :emptyList), :newAttempt)",
236
+ "#createdAt = if_not_exists(#createdAt, :createdAt)",
237
+ ];
238
+ expressionAttributeNames["#attempts"] = "attempts";
239
+ expressionAttributeNames["#createdAt"] = "createdAt";
240
+ // Add all payload fields dynamically
241
+ const allFields = {
242
+ ...payload,
243
+ ...secondaryKeys,
244
+ ttl: ttlAttribute.ttl,
245
+ };
246
+ // Fields that need special handling (already in setClauses)
247
+ const specialFields = new Set(["attempts", "createdAt"]);
248
+ for (const [key, value] of Object.entries(allFields)) {
249
+ if (value === undefined)
250
+ continue;
251
+ expressionAttributeNames[`#${key}`] = key;
252
+ expressionAttributeValues[`:${key}`] = value;
253
+ if (!specialFields.has(key)) {
254
+ setClauses.push(`#${key} = :${key}`);
255
+ }
256
+ }
257
+ const result = await this.client.send(new UpdateItemCommand({
258
+ TableName: DynamoDB.Table.Name(),
259
+ Key: marshall(primaryKey, {
260
+ removeUndefinedValues: true,
261
+ convertEmptyValues: true,
262
+ convertClassInstanceToMap: true,
263
+ }),
264
+ UpdateExpression: `SET ${setClauses.join(", ")}`,
265
+ ExpressionAttributeNames: expressionAttributeNames,
266
+ ExpressionAttributeValues: marshall(expressionAttributeValues, {
267
+ removeUndefinedValues: true,
268
+ convertEmptyValues: true,
269
+ convertClassInstanceToMap: true,
270
+ }),
271
+ ReturnValues: "ALL_NEW",
272
+ }));
273
+ if (!result.Attributes) {
274
+ throw new Error("UpdateItem did not return attributes");
275
+ }
276
+ const updated = unmarshall(result.Attributes);
277
+ return updated.attempts.length;
278
+ }
192
279
  /**
193
280
  * Lists audit records for a specific resource with pagination.
194
281
  *
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
package/dist/service.js CHANGED
@@ -128,35 +128,11 @@ export class AuditService {
128
128
  error: item.error,
129
129
  at: now,
130
130
  };
131
- // Check for existing audit to handle retry tracking
132
- if (item.id) {
133
- try {
134
- const existing = await this.storage.getItem({
135
- id: item.id,
136
- app: item.target.app,
137
- resourceType: item.target.type,
138
- tenantId: item.tenantId,
139
- });
140
- if (existing) {
141
- // Append to existing attempts array
142
- const existingAttempts = existing.attempts ?? [];
143
- currentAttempt.number = existingAttempts.length + 1;
144
- item.attempts = [...existingAttempts, currentAttempt];
145
- // Preserve original createdAt
146
- item.createdAt = existing.createdAt.toISOString();
147
- }
148
- else {
149
- item.attempts = [currentAttempt];
150
- }
151
- }
152
- catch {
153
- // Audit doesn't exist, this is the first attempt
154
- item.attempts = [currentAttempt];
155
- }
156
- }
157
- else {
158
- item.attempts = [currentAttempt];
159
- }
131
+ // Upsert main item with atomic attempt tracking
132
+ // This handles both new items and retries in a single atomic operation
133
+ const attemptNumber = await this.storage.upsertItem(item, currentAttempt);
134
+ currentAttempt.number = attemptNumber;
135
+ // Build batch for related resource items (these don't need retry tracking)
160
136
  const batch = Array.from(item.resources || [])
161
137
  .filter((resource) => !!resource.id)
162
138
  .map((resource) => ({
@@ -172,7 +148,9 @@ export class AuditService {
172
148
  error: undefined,
173
149
  attempts: undefined,
174
150
  }));
175
- await this.storage.upsertBatch([item, ...batch]);
151
+ if (batch.length > 0) {
152
+ await this.storage.upsertBatch(batch);
153
+ }
176
154
  await this.events?.upserted([item]);
177
155
  }
178
156
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flipboxlabs/aws-audit-sdk",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "AWS Audit SDK - Core SDK for audit logging and event management",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",