Skip to content

audit: optional COLLIE_AUDIT_CONTENT=none, keeping the event and dropping the body - #107

Closed
shuangwangnyc wants to merge 1 commit into
AltanS:mainfrom
shuangwangnyc:feat/audit-content-redaction
Closed

audit: optional COLLIE_AUDIT_CONTENT=none, keeping the event and dropping the body#107
shuangwangnyc wants to merge 1 commit into
AltanS:mainfrom
shuangwangnyc:feat/audit-content-redaction

Conversation

@shuangwangnyc

Copy link
Copy Markdown

audit: optional COLLIE_AUDIT_CONTENT=none, keeping the event and dropping the body

The audit trail records every write-level action, which is right — sending
keystrokes to a pane is arbitrary code execution and who-did-what-when is worth
keeping. It also records up to 120 characters of the message itself, and up to
120 characters of the prompt binding, which is a slice of whatever happened to be
on the terminal at the time.

For a personal deployment that is fine. For one where the trail is wanted but the
bodies are not, there is currently no way to have one without the other.

This adds one config value:

COLLIE_AUDIT_CONTENT=preview (default, byte-for-byte today's behaviour)
COLLIE_AUDIT_CONTENT=none every string inside detail becomes the length

The envelope is untouched either way: ts, action, paneId, session, device, and
every boolean and number inside detail. So submitted, textDelivered and
promptBinding.checked/passed still answer the questions the log is for.

Two small decisions, in case they are worth arguing about:

  • It keeps the LENGTH rather than a shorter preview. A truncated secret is still
    a secret, and the question a reader asks of a redacted trail is usually whether
    anything was sent at all, which a count answers.
  • It recurses, so nesting is covered. The prompt binding is nested and holds the
    terminal fragment; a redaction reaching only the top level would have left the
    more sensitive half in place.

sanitize and formatAuditLine take the mode as a defaulted parameter, so every
existing caller and test is unaffected.

Tested: the existing suite passes unchanged (590 tests), plus four new cases
covering the default being untouched, the envelope surviving, nothing of the
message or the terminal surviving at any depth, and the length being preserved.

Happy to adjust the naming, or drop the env var and take a constructor argument
only, if you would rather not add configuration for this.

…ping the body

The audit trail records every write-level action, which is right — sending
keystrokes to a pane is arbitrary code execution and who-did-what-when is worth
keeping. It also records up to 120 characters of the message itself, and up to
120 characters of the prompt binding, which is a slice of whatever happened to be
on the terminal at the time.

For a personal deployment that is fine. For one where the trail is wanted but the
bodies are not, there is currently no way to have one without the other.

This adds one config value:

  COLLIE_AUDIT_CONTENT=preview   (default, byte-for-byte today's behaviour)
  COLLIE_AUDIT_CONTENT=none      every string inside `detail` becomes the length

The envelope is untouched either way: ts, action, paneId, session, device, and
every boolean and number inside detail. So submitted, textDelivered and
promptBinding.checked/passed still answer the questions the log is for.

Two small decisions, in case they are worth arguing about:

- It keeps the LENGTH rather than a shorter preview. A truncated secret is still
  a secret, and the question a reader asks of a redacted trail is usually whether
  anything was sent at all, which a count answers.
- It recurses, so nesting is covered. The prompt binding is nested and holds the
  terminal fragment; a redaction reaching only the top level would have left the
  more sensitive half in place.

sanitize and formatAuditLine take the mode as a defaulted parameter, so every
existing caller and test is unaffected.

Tested: the existing suite passes unchanged (590 tests), plus four new cases
covering the default being untouched, the envelope surviving, nothing of the
message or the terminal surviving at any depth, and the length being preserved.

Happy to adjust the naming, or drop the env var and take a constructor argument
only, if you would rather not add configuration for this.
@AltanS

AltanS commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Thanks @shuangwangnyc — this was a real gap and the shape you picked (COLLIE_AUDIT_CONTENT=preview|none, envelope kept, bodies dropped) is exactly what landed. Merged via #111 with your commit cherry-picked in, authorship preserved; the follow-up on top changes the redaction to decide by field role with a fail-closed allowlist (so key names stay legible while anything operator- or screen-originated redacts by default) and swaps the exact length for a flat ⟨redacted⟩. It'll ship with the next release.

@AltanS AltanS closed this Aug 17, 2026
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.

2 participants