All skills
nangohq avatar

/adding-audit-events

@91109d1
by Nangonangohq/nango12k stars
1,400

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

Use this Skill: https://skilld.dev/gh/nangohq/nango/adding-audit-events

This session only. Nothing lands on disk.

SKILL.md

β‰ˆ55 tokens always: the name and description. β‰ˆ1k when used: this file.

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:

    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

Source: SKILL.md on GitHub

No alerts11d3 checks Β· Risk SAFE
  • Gen Agent Trust Hub11d

    The skill provides instructional guidance and code patterns for implementing audit logging within the Nango codebase. It defines workflows for metadata, middleware, and routing without including any executable code, external dependencies, or malicious patterns.

  • Socket11d

    No alerts

  • Snyk11d

    Risk: LOW Β· No issues

Signed by skilld at 91109d1. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 7 hours ago.

Activeupdated last month

README badge

README badge for nangohq/nango/adding-audit-events