Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6c1cf06
Feature/ak 001 core domain types (#3)
y-aithnini Mar 13, 2026
370361d
core audit service implementation (#4)
y-aithnini Mar 16, 2026
e82150b
implemented adapter (#5)
y-aithnini Mar 16, 2026
a303774
implemented utility providers (#6)
y-aithnini Mar 17, 2026
be23582
implemented nestjs module (#7)
y-aithnini Mar 18, 2026
ce8e606
Feature/ak 006 comprehensive testing (#8)
y-aithnini Mar 23, 2026
4dea4b8
fixed mongodb repository tests results (#9)
y-aithnini Mar 24, 2026
9373521
implemented remaining test fixes (#10)
y-aithnini Mar 25, 2026
489e087
feat: add retention redaction idempotency and config validation
y-aithnini Mar 25, 2026
0b52904
fix: use compatible ignoreDeprecations value
y-aithnini Mar 25, 2026
e9ce193
feat: add cursor pagination, OTel observer hooks, mutation testing, a…
y-aithnini Mar 26, 2026
ee86de4
feat: add event streaming, docs updates, and CI compatibility matrix
y-aithnini Mar 26, 2026
27c8694
style: enforce LF line endings and add .gitattributes
y-aithnini Mar 26, 2026
8a60f9c
fix: resolve SonarCloud quality gate failures and warnings
y-aithnini Mar 26, 2026
49ac99c
Feature/ak 009 retention redaction idempotency validation (#11)
y-aithnini Mar 27, 2026
2a7c1d8
fix: update @nestjs/common to 11.1.17 to patch file-type CVEs
y-aithnini Mar 27, 2026
aa0ddaa
Feature/ak 009 retention redaction idempotency validation (#13)
y-aithnini Mar 27, 2026
c6b5255
refactor: remove MongoDB adapter, add custom repository config
y-aithnini Mar 27, 2026
1a26143
chore: merge develop and resolve conflicts (keep custom repository, r…
y-aithnini Mar 27, 2026
46221cc
chore: release v0.1.0
y-aithnini Mar 30, 2026
a2f8fc2
chore: merge develop (simplify CI to ubuntu/Node 22)
y-aithnini Apr 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .changeset/thick-maps-raise.md

This file was deleted.

14 changes: 14 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Enforce LF line endings for all text files on all platforms
* text=auto eol=lf

# Explicitly declare binary files to prevent corruption
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.woff binary
*.woff2 binary
*.ttf binary
*.otf binary
*.eot binary
3 changes: 2 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
"semi": true,
"singleQuote": false,
"trailingComma": "all",
"printWidth": 100
"printWidth": 100,
"endOfLine": "lf"
}
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# @ciscode/audit-kit

## 0.1.0

### Minor Changes

- Initial feature release of @ciscode/audit-kit.
- Cursor-based (keyset) pagination via `queryWithCursor()`
- OpenTelemetry-compatible observer hooks (`IAuditObserver`)
- Audit event streaming adapter (`IAuditEventPublisher`, `EventEmitterAuditEventPublisher`)
- PII redaction, idempotency, and retention policies
- Custom repository config (`type: "custom"`) — bring your own repository from a database package
- In-memory repository for testing
- Stryker mutation testing configuration
- Vitest performance benchmarks
- CI compatibility matrix (Ubuntu + Windows × Node 20 + 22)
163 changes: 140 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,148 @@
# NestJS DeveloperKit (Template)
# @ciscode/audit-kit

Template repository for building reusable NestJS npm packages.
AuditKit is a reusable NestJS module for immutable audit logging with clean architecture (`core` / `infra` / `nest`).

## What you get
It provides:

- ESM + CJS + Types build (tsup)
- Jest testing
- ESLint + Prettier
- Changesets (Release PR flow)
- Husky (pre-commit + pre-push)
- Enforced package architecture (core / infra / nest) with strict public API
- Framework-free core service (`AuditService`)
- Pluggable repositories (MongoDB, in-memory)
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

README claims "Pluggable repositories (MongoDB, in-memory)", but the public RepositoryConfig type only allows type: "in-memory" | "custom" and there is no MongoDB adapter in this PR. This is misleading for consumers; either implement and document MongoDB support, or update the README to describe the supported repository types (in-memory + custom).

Suggested change
- Pluggable repositories (MongoDB, in-memory)
- Pluggable repositories (in-memory + custom adapter)

Copilot uses AI. Check for mistakes.
- Automatic change detection
- Configurable redaction, idempotency, and retention policies
- Cursor-based pagination for stable listing
- Observability hooks (OpenTelemetry-friendly observer port)
- Event streaming hooks (publisher port + default EventEmitter adapter)

## Scripts
## Install

- `npm run build` – build to `dist/`
- `npm test` – run tests
- `npm run typecheck` – TypeScript typecheck
- `npm run lint` – ESLint
- `npm run format` / `npm run format:write` – Prettier
- `npx changeset` – create a changeset
```bash
npm install @ciscode/audit-kit
```

## Release flow (summary)
Peer dependencies are managed by consuming applications.

- Work on a `feature` branch from `develop`
- Merge to `develop`
- Add a changeset for user-facing changes: `npx changeset`
- Automation opens “Version Packages” PR into `master`
- Merge to `master`, tag `vX.Y.Z` to publish
## Quick Start

See `docs/RELEASE.md` for details.
```typescript
import { Module } from "@nestjs/common";
import { AuditKitModule } from "@ciscode/audit-kit";

@Module({
imports: [
AuditKitModule.register({
repository: {
type: "in-memory",
},
redaction: {
enabled: true,
fields: ["actor.email", "metadata.password"],
mask: "[REDACTED]",
},
idempotency: {
enabled: true,
keyStrategy: "idempotencyKey",
},
}),
],
})
export class AppModule {}
```

## Usage

```typescript
import { Injectable } from "@nestjs/common";
import { ActorType, AuditActionType, AuditService } from "@ciscode/audit-kit";

@Injectable()
export class UserService {
constructor(private readonly auditService: AuditService) {}

async updateUser(): Promise<void> {
await this.auditService.log({
actor: { id: "user-1", type: ActorType.USER, email: "user@example.com" },
action: AuditActionType.UPDATE,
resource: { type: "user", id: "user-1" },
metadata: { reason: "profile update" },
idempotencyKey: "req-123",
});
}
}
```

## Advanced Features

### Cursor Pagination

```typescript
const page1 = await auditService.queryWithCursor({ actorId: "user-1" }, { limit: 20 });

if (page1.hasMore) {
const page2 = await auditService.queryWithCursor(
{ actorId: "user-1" },
{ limit: 20, cursor: page1.nextCursor },
);
}
```

### Observability Hooks

Provide an observer to emit metrics/spans/log events (for OpenTelemetry, Prometheus, etc.):

```typescript
AuditKitModule.register({
repository: { type: "in-memory" },
observer: {
onEvent(event) {
// event.operation, event.durationMs, event.success
console.log(event);
},
},
});
```

### Event Streaming

Emit domain events after successful audit creation:

```typescript
AuditKitModule.register({
repository: { type: "in-memory" },
eventStreaming: {
enabled: true,
// optional custom publisher; default is EventEmitter adapter
publisher: {
publish(event) {
console.log(event.type, event.payload.id);
},
},
},
});
```

## Tooling

- Tests: `npm test`
- Typecheck: `npm run typecheck`
- Lint: `npm run lint`
- Build: `npm run build`
- Mutation testing: `npm run mutation`
- Benchmarks: `npm run bench`

## CI Compatibility Matrix

PR validation runs on a matrix to catch environment regressions early:

- Node.js: 20, 22
- OS: ubuntu-latest, windows-latest

See [.github/workflows/pr-validation.yml](.github/workflows/pr-validation.yml).

## Release Flow (Summary)

1. Work on a feature branch from `develop`
2. Add a changeset for user-facing changes: `npx changeset`
3. Merge into `develop`
4. Automation opens "Version Packages" PR into `master`
5. Merge and publish

See [docs/RELEASE.md](docs/RELEASE.md) for details.
32 changes: 32 additions & 0 deletions __mocks__/nanoid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Jest mock for nanoid ESM module
*
* SECURITY NOTE: This mock uses Math.random() which is NOT cryptographically secure.
* This is acceptable because:
* 1. This code is ONLY used in Jest tests, never in production
* 2. Test IDs don't require cryptographic security
* 3. The real nanoid library (used in production) uses crypto.randomBytes()
*
* SonarQube Security Hotspot Review: Accepted as safe for test-only code
*/

export const nanoid = jest.fn((size = 21) => {
let result = "";
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
for (let i = 0; i < size; i++) {
// NOSONAR: Math.random() is acceptable for test mocks
result += chars.charAt(Math.floor(Math.random() * chars.length)); // NOSONAR
}
return result;
});

export const customAlphabet = jest.fn((alphabet: string, defaultSize = 21) => {
return (size = defaultSize) => {
let result = "";
for (let i = 0; i < size; i++) {
// NOSONAR: Math.random() is acceptable for test mocks
result += alphabet.charAt(Math.floor(Math.random() * alphabet.length)); // NOSONAR
}
return result;
};
});
Loading
Loading