Skip to main content

Citadel

Citadel applies a YAML de-identification policy to JSON or JSONL records and writes the transformed data to an explicit output path.

uvx tacit-citadel policy.yaml input.json output.json

For local development from this checkout:

uv run tacit-citadel policy.yaml sample.jsonl sample.citadel.jsonl

The PyPI package and installed console command are both tacit-citadel.

Project-specific policies can live with the dataset they are used for. The checked-in policy.yaml and sample.jsonl are generic support-ticket examples for local smoke tests.

Policy Shape

Policies have deterministic path-based rules and an optional whole-record rewrite step.

version: 1
name: support-ticket-sanitizer
description: De-identification policy for customer support tickets.

validators:
  - path: .customer.contract_value_usd
    action: number_range
    params:
      min: 1
      max: 100000000

rewrite:
  backend: codex exec
  sandbox: read-only
  system_prompt: You are a conservative de-identification rewriter.
  user_prompt: |
    Rewrite the INPUT JSON object.

    INPUT JSON
    {{content}}
  preserve:
    - path: .customer.contract_value_usd
      required: false

rules:
  - path: .account.id
    action: drop

rewrite.backend must be codex exec or claude -p. Rewrites always receive the whole record after deterministic rules have run and must return a complete JSON object. rewrite.preserve selectors snapshot values after deterministic rules and require the same values after the rewrite; required defaults to true. If a rewrite fails, returns invalid JSON, or changes a preserved value after three attempts, Citadel logs an error, aborts the run, and does not write the output file.

Validators

Validators run before deterministic rules and rewrite. If a record fails any validator, Citadel omits that record from the output.

number_range requires every matched value to be numeric and within inclusive min / max bounds. At least one bound is required. required defaults to true; a missing required validator path skips the record.

validators:
  - path: .intake_details.weight
    action: number_range
    params:
      min: 30
      max: 300

Rules

path is a small jq-like selector. It supports dotted object fields, list wildcards, numeric list indexes, quoted bracket fields, and simple | select(.field == "value") / | select(.field != "value") filters.

required defaults to true. Use required: false for sparse paths.

drop

Deletes matched object fields.

- path: .account.id
  action: drop

fuzz_number

Perturbs numeric values with either percentage or range mode.

- path: .customer.contract_value_usd
  action: fuzz_number
  params:
    mode: percent
    max_percent: 3
    precision: 0
- path: .risk_score
  action: fuzz_number
  params:
    mode: range
    min_delta: -1
    max_delta: 1
    step: 1

date_offset

Replaces date or datetime strings with a day offset from an anchor date.

- path: .events[].timestamp
  action: date_offset
  required: false
  params:
    anchor_path: .reported_at
    output: human_relative

Outputs are same day, N day later, N days later, N day ago, or N days ago.

Inputs

Citadel accepts:

  • a JSON object
  • a JSON array of objects
  • JSONL with one object per non-empty line

The output format matches the input shape. Skipped JSONL records are omitted, skipped JSON array items are removed, and a skipped single JSON object writes null.

Development

The implementation is intentionally contained in run.py.

uv run pytest
uv run ruff check .
uv run ty check

Metadata

Release files for tacit-citadel 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tacit-citadel 0.3.0
File Size Uploaded
tacit_citadel-0.3.0.tar.gz 15.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tacit-citadel 0.3.0
File Interpreter ABI Platform
tacit_citadel-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 25.4 kB

Release files / tacit_citadel-0.3.0.tar.gz

Download URL tacit_citadel-0.3.0.tar.gz
Size 15.1 kB
Tags Source
SHA-256 checksum
How to use checksums
cba2f1d5afc0301322b6b923600e80134c5766471f89fc11226e9969b7ed9aec
BLAKE2b-256 checksum
How to use checksums
d0dcc9751c8d3da45fedecb7b6a8d223504f23e323f88f3b70f3a3ba4eeffc4a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / tacit_citadel-0.3.0-py3-none-any.whl

Download URL tacit_citadel-0.3.0-py3-none-any.whl
Size 10.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
da410a01681e469b80da5913651904422c01561d261e60196b907f2e79a5a5ea
BLAKE2b-256 checksum
How to use checksums
56d0289eeff792347a62b5fa41dab64a8815b43636f6c711c9220af58f95ac65
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page