Skip to content

feat(audit): declare how each mutation is recorded in its procedure meta - #121

Open
toto04 wants to merge 1 commit into
Diubii/audit-logfrom
audit/procedure-meta
Open

toto04 wants to merge 1 commit into
Diubii/audit-logfrom
audit/procedure-meta

Conversation

@toto04

@toto04 toto04 commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

Stacked on #90. This is the work its review comment asks for before #90 merges: every mutation declares how the audit log records it, in its procedure meta next to its policy, and a router test enforces it.

What changes

The option (src/audit/option.ts, no imports, so declaring one doesn't load the database schema):

Option What is stored Used for
audit.full({ fields?, target? }) actor, action, target, outcome, plus the input (only fields, when given), the reason and the states the handler adds with ctx.audit.set web content, groups, labels, WhatsApp, Telegram groups and grants, e-signing, Azure
audit.minimal({ target? }) actor, action, target, outcome People, whose details stay in people_activity
audit.none(why) nothing; why is required tg.messages.add, tg.users.add, tg.auditLog.record, esign.profile.sync
  • The option's target gets the raw input and, once the call succeeds, its result. A target the handler sets with ctx.audit.set takes precedence.
  • The action is still the procedure path, so event names already stored stay valid. action can override it if a procedure is ever renamed.
  • Router test: fails when any mutation lacks an option, or when a none option has no why. At runtime, a mutation without an option is recorded as minimal and logged as an error.
  • Removed: UNAUDITED and the temporary path-prefix rule for People.

Annotations

  • People: the base procedure of the router factory is minimal. The person comes from a valid P-NNNN id in the input (personId or id) or from the created record. The router test checks the target function, including that an invalid raw id gives no target.
  • E-signing:
    • requests.create keeps the title, document, order, signers and output. It no longer keeps the email recipients or message.
    • Its recorded state after the change now names the signers by subject, role and position only. It used to store the whole request, including signers' fiscal codes, certificate subjects and email settings.
    • requests.decline keeps the id, and the reason in its own column.
  • Azure:
    • setAssocNumber keeps the member's id and number, not the notification address.
    • create keeps the number and the mailbox choice, not the names or the welcome-email address. The name is still the target's label.
    • The state recorded after create no longer contains the new email address.

Not included

Checks

  • npx tsc --noEmit, npx biome check and npx vitest run pass (337 tests).
  • New tests cover none, minimal, input fields, the undeclared fallback, target precedence and People's target function.

Every mutation now says how the audit log records it, next to its policy, and a
router test fails when one does not, so a new area cannot store full inputs
without anyone deciding it:

- audit.full({ fields?, target? }): the input (only `fields`, when given), the
  reason and the states the handler adds.
- audit.minimal({ target? }): the actor, the action, the target and the outcome.
- audit.none(why): not recorded, with the reason in the code.

The option replaces the UNAUDITED set and the temporary rule for People:

- People's base procedure is minimal, with the person taken from a valid People
  id in the input or the created record; the router test checks both.
- The bot's ingestion, its moderation reports and the e-signing profile sync are
  none.
- E-signing keeps the request's title, document, signers and output, not the email
  recipients or message, and its state after names the signers by subject and
  position, without their fiscal codes or certificates. A decline keeps its id and
  reason.
- Azure keeps the member's directory id and number, not names, the notification
  address or the new mailbox address.

The helpers live in src/audit/option.ts, which imports nothing, so declaring an
option does not load the database schema. A mutation without one is recorded as
minimal and logged.
@coderabbitai

coderabbitai Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

Walkthrough

Audit recording now uses per-mutation options for full, minimal, or disabled capture. The audit middleware passes these options to event creation. Multiple routers declare capture options, including selected input fields and explicit exclusions.

Changes

Audit capture policy and event recording

Layer / File(s) Summary
Define capture options and event recording
src/audit/option.ts, src/audit/index.ts, src/trpc.ts, tests/audit-json.test.ts, README.md
Audit options define full, minimal, and disabled capture. The middleware passes the option to event creation. Tests cover detail omission, field filtering, and target selection. The documentation describes the capture modes and related filtering.
Set People audit targets
src/people/router.ts, tests/idp-router.test.ts
The People user policy declares minimal capture and derives targets from valid People IDs in input or result data. Tests check target selection and audit metadata on mutations.
Declare capture for application mutations
src/routers/groups/labels.ts, src/routers/wa/groups.ts, src/routers/web/*, tests/group-label-platform-isolation.test.ts, tests/guides-latest.test.ts
Group-label, WhatsApp-group, and web mutations declare full capture. Test procedure mocks support .meta() chaining.
Limit Azure and e-sign audit data
src/routers/azure/members.ts, src/routers/esign.ts, tests/azure-router.test.ts
Azure and e-sign mutations declare capture options. Azure member creation omits email from its after data. E-sign request creation records selected request and signer fields.
Declare Telegram capture and exclusions
src/routers/tg/*, tests/tg-users-creation-history.test.ts
Telegram group and grant mutations declare full capture. Moderation-log and bot-ingestion procedures declare no capture with reasons. The test mock supports .meta() chaining.

Possibly related issues

  • Issue 119 distinguishes stored-data limits from reader redaction. This change limits some stored audit data, but does not describe or implement reader redaction.

Change: Feature

Merge Risk: Low · up to 7da88

A crafted failed request can put the wrong ID in an audit record. The edge case is narrow and can be followed up without blocking merge.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title clearly describes the main change: each mutation declares its audit-recording policy in procedure metadata.
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 2 functions across 25 files. (1 skipped: 1 unsupported.)

Finishing Touches

Generate docstrings

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@toto04
toto04 requested review from BIA3IA and lorenzocorallo and removed request for lorenzocorallo November 9, 2026 02:39

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Additional comments: 1

src/routers/web/reports.ts: 1

33-33: Trivial · Maintainability & Code Quality · Low value

Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.

Public report creation records the full input under audit.full().

create is reachable with the publicRead service scope. The input includes free text (label, details) and a URL chosen by the caller. audit.full() stores all of it. This conflicts with the PR goal of avoiding free text that is not worth keeping. Consider audit.full({ fields: [...] }) or audit.minimal. The handler already sets after: report, so the input copy duplicates data.

Review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between b0f81d5 and 7da88a4.

Files selected for processing: 26

  • README.md
  • src/audit/index.ts
  • src/audit/option.ts
  • src/people/router.ts
  • src/routers/azure/members.ts
  • src/routers/esign.ts
  • src/routers/groups/labels.ts
  • src/routers/tg/audit-log.ts
  • src/routers/tg/grants.ts
  • src/routers/tg/groups.ts
  • src/routers/tg/messages.ts
  • src/routers/tg/users.ts
  • src/routers/wa/groups.ts
  • src/routers/web/associations.ts
  • src/routers/web/faqs.ts
  • src/routers/web/freshman.ts
  • src/routers/web/guides_matricole.ts
  • src/routers/web/projects.ts
  • src/routers/web/reports.ts
  • src/trpc.ts
  • tests/audit-json.test.ts
  • tests/azure-router.test.ts
  • tests/group-label-platform-isolation.test.ts
  • tests/guides-latest.test.ts
  • tests/idp-router.test.ts
  • tests/tg-users-creation-history.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

@toto04
toto04 requested a review from Diubii November 10, 2026 11:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant