Skip to main content

adding-audit-events

Use when adding or changing an audited Nango endpoint, or deciding one shouldn't be audited - covers the vocabulary table, metadata typing, spec placement, mount ordering, and the webapp filter list

소스 정보

저장소
NangoHQ/nango
최근 소스 활동
2026년 8월 31일 07:37
감지된 SKILL.md 언어
영어
스타
12,607
포크
1,429

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
adding-audit-events
description
Use when adding or changing an audited Nango endpoint, or deciding one shouldn't be audited - covers the vocabulary table, metadata typing, spec placement, mount ordering, and the webapp filter list
# Adding Audit Events `AuditEventTable` in `packages/types/lib/audit-trail/event.ts` is the source of truth: it maps each resource to its actions and the metadata each may carry. The event union, the metadata lookup, the per-resource action lists and the webapp filters all derive from it. Add the action there first and let the compiler tell you what else to touch. The trail is **control-plane only** — configuration, state and authentication. Runtime traffic (records, proxy, sync execution) is data plane and stays out; audit it and you get millions of rows a month. ## Workflow 1. **Vocabulary** — in `AuditEventTable`, under the resource: `<action>: <MetadataShape>;` or `<action>: never;` when the action carries no metadata. 2. **Metadata shape**, if any — `packages/types/lib/audit-trail/metadata.ts`. Name it for what it holds, never for one action: `integration.created` and `integration.deleted` share `IntegrationProviderMetadata` because both record only the provider. 3. **Endpoint type** — every customer-facing endpoint declares one: - `Audit: AuditPolicy<'<resource>', '<action>', 'account' | 'environment'>` - `Audit: { kind: 'no-audit'; reason: '<why>' }` — use `'data-plane operation'` for runtime traffic. 4. **Spec** — `packages/server/lib/middleware/audit/<resource>.middleware.ts`: ```ts export const auditThingDone = auditable<PostThing>({ policy: Audit.auditable({ resource: 'thing', action: 'done', scope: 'environment' }), target: (req) => makeTarget('thing', nonEmptyString(req.body.id)), metadata: (req) => omitUndefined<ThingDoneMetadata>({ … }) }); ``` Mounted middleware first, in the vocabulary's action order, private spec then public for the same action; multi-action emitters last; helpers below all of them. 5. **Barrel** — add the export to `audit/index.ts`. Hand-written on purpose: it declares what has scope beyond the folder, so never `export *`. 6. **Mount** — `routes.public.ts` / `routes.private.ts`, **before `withScope`**: `.post(apiAuth, auditThingDone, withScope('…'), handler)`. After the scope check, denials are lost. 7. **Test** — `<resource>.middleware.unit.test.ts`, scaffolding from `./testing.js`. 8. **Webapp** — add the action to `actionsByResource` in `packages/webapp/src/pages/Audit/constants.ts`. A type check pins it to the vocabulary, so omitting it is a build error. Labels are derived. 9. **New kind of target** — add it to `AuditTargetType`. ## Gotchas - **Resolvers run before zod.** `req.body` / `params` / `query` are raw at that point, whatever the endpoint type says. Use the guards in `input.ts`: `nonEmptyString`, `positiveInt`, `param`, `query`, `bodyField`. - **`target` and `metadata` resolve before `next()`**, so a value the handler generates isn't available yet. Use `targetFromResponse` / `metadataFromResponse`. - **A 403 means no handler ran**, so anything only the handler knows is missing from exactly the rows an auditor cares about most. Prefer reading from the request. - **`scope: 'account'` nulls the event's environment**, whatever `res.locals` holds. - **On the MCP path only** (`defineManagementMcpTool`), a stray metadata key *alongside* a valid one is accepted — the audit type is a union over the vocabulary. A stray key alone, a wrong type, and metadata on a `never` action all fail. - **Grep `input.ts` and `lookups.ts` before adding a helper.** The target and metadata builders usually exist, and near-identical `…Target` functions get flagged in review. ## Review Checklist - [ ] `npm run ts-build` clean — it catches a missing webapp entry, metadata that doesn't fit the action, and metadata on an action declared `never` - [ ] Unit test asserts the common fields (`accountId`, `environment`, `actor`, `outcome`), not only the one it is named for - [ ] Test break-checked: remove the target or a metadata key and confirm it goes red - [ ] Audit middleware sits before `withScope` on every new mount - [ ] Denial and failure paths still identify the event — check what a 403 records, not just the 200
GitHub에서 보기