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

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tacit_citadel-0.3.0.tar.gz (15.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tacit_citadel-0.3.0-py3-none-any.whl (10.3 kB view details)

Uploaded Python 3

File details

Details for the file tacit_citadel-0.3.0.tar.gz.

File metadata

  • Download URL: tacit_citadel-0.3.0.tar.gz
  • Upload date:
  • Size: 15.1 kB
  • Tags: Source
  • Uploaded using 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}

File hashes

Hashes for tacit_citadel-0.3.0.tar.gz
Algorithm Hash digest
SHA256 cba2f1d5afc0301322b6b923600e80134c5766471f89fc11226e9969b7ed9aec
MD5 6af0725c5cba35d89432495af76b2fa0
BLAKE2b-256 d0dcc9751c8d3da45fedecb7b6a8d223504f23e323f88f3b70f3a3ba4eeffc4a

See more details on using hashes here.

File details

Details for the file tacit_citadel-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: tacit_citadel-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 10.3 kB
  • Tags: Python 3
  • Uploaded using 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}

File hashes

Hashes for tacit_citadel-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 da410a01681e469b80da5913651904422c01561d261e60196b907f2e79a5a5ea
MD5 9580dd7b461885128dced9ba1bd784c3
BLAKE2b-256 56d0289eeff792347a62b5fa41dab64a8815b43636f6c711c9220af58f95ac65

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page