Pre-send review, safe rewrite, and audit evidence for GenAI, email, and document sharing.
Junas is not a DOM-only blur overlay. It reviews submitted text and supported documents before users paste prompts, send email, upload matter files, or share drafts externally; image/OCR paths can inspect image-backed content when OCR is configured. The deterministic review engine is the runtime source of truth: it detects personal data and material non-public information, returns statute-cited findings, records audit-ready evidence, and routes users toward safe rewrite, redaction, pseudonymization, approval, or hold actions.
Project status: pre-production / portfolio-stage. The deterministic core, policy contract, demo artifacts, and supported-target adapter evidence are present; production hardening, independent eval expansion, hosted demo, and rollout tasks remain tracked in GitHub issues, including #84 and #85. Public demo evidence and limitations are documented in docs/public-demo.md.
Primary first-run path from a checkout:
uv sync --extra dev
uv run python -m spacy download en_core_web_sm
uv run python scripts/preflight.py --strict
./scripts/demo.shStart the local API after the demo:
./scripts/launch/run_backend_only.sh
curl http://127.0.0.1:8000/readyPackaged DMG, Homebrew, Nix, and signed desktop install paths are not the default README path yet. Developer verification and packaging commands live under Development & Evaluation and Packaging & Deployment.
Generated by python3 scripts/export_openapi_examples.py from a real local /review run. Full artifacts: request, response.
| Confidential input | Junas verdict |
|---|---|
Subject: Project Raven draft |
send_allowed: falsepolicy_decision: blockoverall_risk: HIGH_RISKpii_score: 88.0 / mnpi_score: 100.0required_actions: hold_until_public, redact_pii, request_approval, safe_rewrite |
| Finding | Generated legal basis | Generated citation string |
|---|---|---|
PII:sg_nric_fin on S1234567D |
SG_PDPA_PERSONAL_DATA, SG_PDPA_SENSITIVE_CONTEXT, US_PRIVACY_BASELINE |
"S1234567D" detected => PDPA s13 and PDPC NRIC Advisory (effective 31 Dec 2026): NRIC/FIN must not be collected, used, or disclosed without explicit purpose and consent. Mask before send. Reference: Personal Data Protection Act 2012. Reference: applicable U... |
MNPI:transaction_codename on Project Raven |
SG_SFA_INSIDE_INFORMATION, SG_SFA_GENERALLY_AVAILABLE, US_MNPI_INSIDER_TRADING, US_REG_FD_PUBLIC_DISCLOSURE |
"Project Raven" detected => Internal deal codename detected. Treat as MNPI until the underlying transaction is publicly announced; do not reference the codename in external communications. Reference: Securities and Futures Act 2001 ss215, 218, 219 (insider... |
blocking_findings: mnpi:definitive_agreement:97:100:3, mnpi:transaction_codename:102:115:2, mnpi:transaction_codename:9:22:1, pii:sg_nric_fin:77:86:0
8-second README-friendly SVG loop · fake credentials only · terminal and redacted preview shown side by side
60-second narrated video · Static fallback PNG for readers who disable animation · Regenerate the capture
- Install Locally
- Why Junas
- What This Is / What This Is NOT
- Default Privacy Posture
- Demo
- Quick Start
- Troubleshooting
- What Junas Does
- Primary Product Spine
- Design Principles
- Adapter Maturity
- Experimental Local Fallback
- API Surface
- Examples
- How It Works
- Jurisdiction Coverage
- Known Limitations
- Accuracy & Evaluation
- Runtime Modes
- Documentation
- Development & Evaluation
- Contributing
- Packaging & Deployment
- Screenshots
- License
A paralegal asks a public GenAI tool to turn a draft Project Raven term sheet into a client update. The prompt includes an SG NRIC, a deal codename, draft SPA language, and an acquisition price that has not been announced. A normal paste box treats that as text; a reviewer sees personal data, MNPI, cross-border context, and audit exposure after the fact. Junas moves that check to pre-send and pre-paste time: the workflow calls /review, gets deterministic findings and policy actions, then redacts, holds, or routes for approval before content leaves the trusted boundary. See docs/product/positioning.md for canonical positioning and non-goals.
| What this is | What this is NOT |
|---|---|
| Junas reviews explicit workflow submissions and can feed decisions/evidence into DLP-led programs. | Junas does not replace DLP policy, network inspection, endpoint discovery, SaaS storage scanning, or enterprise data classification. |
| Junas surfaces findings, policy reasons, and reviewer workflow evidence for qualified reviewers. | Junas does not provide legal advice, privilege calls, matter strategy, or external counsel review. |
| Junas can retain audit evidence about pre-send review decisions when configured. | Junas does not replace legal hold, collection, processing, review platforms, production, or chain-of-custody systems. |
| Junas desktop features are local fallback surfaces, not enterprise endpoint enforcement. | Junas does not replace device management, USB controls, clipboard governance, screen capture controls, file-system policy, or EDR. |
| Junas browser/DMS/API integrations target specific workflows and should coexist with CASB controls. | Junas does not replace cloud-app discovery, sanctioning, session control, or cross-SaaS activity policy. |
| Junas consumes tenant/auth context from trusted identity infrastructure and rejects caller-supplied tenant authority. | Junas does not replace SSO, MFA, conditional access, group policy, or identity lifecycle management. |
See docs/product/non-goals.md for the canonical boundaries.
Junas collects no product telemetry in default local or deterministic demo use. There is no Junas cloud account, sync service, upsell flow, or Sponsor prompt required to run the local backend, demo, browser extension, Office add-ins, desktop watcher, or direct API examples from this repo.
Operator-configured SIEM, Prometheus, adapter telemetry, journals, mappings, and audit packs are customer-controlled deployment surfaces. They stay optional, must avoid raw content, and are documented under docs/admin-security.md, docs/observability-metrics.md, docs/integrations/telemetry.md, and docs/security/data-retention.md.
Run the deterministic demo:
./scripts/demo.shIt starts a local backend, disables public-evidence and LLM paths, and prints three statute-cited verdicts: SG NRIC PII, M&A MNPI, and clean internal text. It does not require provider keys or a spaCy model download. CI runs this script from checkout under a 120-second timeout after Python and uv setup.
Render fake-only reproduction text without starting the backend:
uv run junas demo
uv run junas demo --case browser-prompt --frames 1junas demo prints deterministic FAKE/DEMO secret and PII-shaped examples for screenshots, tweets, and bug reports. The values are synthetic and intentionally avoid real credential shapes.
Docker equivalent:
docker compose -f docker-compose.demo.yml up --build --abort-on-container-exit --exit-code-from demoThe demo uses the same /review contract as adapters and CI:
- SG NRIC in a GenAI prompt: expects
send_allowed: falsewith a rewrite/redact path. - M&A MNPI before announcement: expects
send_allowed: falsewith hold/approval actions. - Clean internal text: expects
send_allowed: true.
The CI One-command demo job runs ./scripts/demo.sh headlessly and fails if those decisions drift.
After Install Locally, start the deterministic backend:
./scripts/launch/run_backend_only.shCheck readiness:
curl http://127.0.0.1:8000/readyReview a document before sending:
curl -X POST http://127.0.0.1:8000/review \
-H "Content-Type: application/json" \
-d '{
"text": "Send Dr Jane Tan S1234567D the confidential draft.",
"source_jurisdiction": "SG",
"destination_jurisdiction": "US",
"document_type": "SPA"
}'Use follow-on actions when the review result requires content changes:
curl -X POST http://127.0.0.1:8000/pseudonymize -H "Content-Type: application/json" -d '{"text":"Send Dr Jane Tan S1234567D the confidential draft."}'
curl -X POST http://127.0.0.1:8000/redact-pii -H "Content-Type: application/json" -d '{"text":"Send Dr Jane Tan S1234567D the confidential draft."}'
curl -X POST http://127.0.0.1:8000/hold-until-public -H "Content-Type: application/json" -d '{"text":"Acme Corp will acquire GlobalTech before announcement."}'
curl -X POST http://127.0.0.1:8000/cite-public-source -H "Content-Type: application/json" -d '{"text":"Acme Corp will acquire GlobalTech before announcement.","entity_id":"Acme Corp"}'
curl -X POST http://127.0.0.1:8000/redact -H "Content-Type: application/json" -d '{"text":"Send Dr Jane Tan S1234567D the confidential draft."}'
DOC_B64="$(base64 -i draft.docx | tr -d '\n')"
curl -X POST http://127.0.0.1:8000/documents/scrub -H "Content-Type: application/json" -d "{\"document_base64\":\"${DOC_B64}\",\"document_filename\":\"draft.docx\"}"Check local capture/OCR setup without telemetry:
uv run junas doctorjunas doctor reports pass/warn/fail diagnostics for ScreenCaptureKit permissions, CoreMediaIO DAL plugins, virtual-camera setup, optional OBS reachability, and Tesseract data paths. It prints local remediation steps and does not collect or transmit telemetry.
- Detects PII and personal data across universal identifiers, jurisdiction-specific IDs, special-category data, quasi-identifiers, and privacy-handling events.
- Detects MNPI and inside-information signals such as material events, non-public markers, deal codenames, tipping language, selective disclosure risk, blackout windows, ESG/cyber/crypto pre-disclosure, sector MNPI, and conjunctive MNPI evidence.
- Applies source and destination jurisdictions with strictest-wins scoring.
- Returns findings, scores, suggestions, statutory rationales, timings, degraded-mode metadata, and optional audit evidence.
- Rewrites text through distinct data states:
/pseudonymize: reversible deterministic placeholders plus mapping./anonymize: irreversible placeholder-only output with no retained mapping./redact: opaque markers without original matched text in the redaction response./redact-pii: deterministic PII-only replacement while MNPI remains visible and flagged./hold-until-public: high-severity MNPI hold text with display-safe and audit-ready reasons./cite-public-source: audit-grade public-source citations with privacy-ledger evidence./request-approval: pending approval journal entry plus reviewer-role requirements.
- Restores reversible pseudonymized text through
/reidentifywhen the caller supplies a mapping or a persisted document hash. - Scrubs supported document metadata leakage through
/documents/scrub. - Keeps optional public evidence and LLM helper layers disabled unless explicitly enabled by deployer and tenant gates.
Junas is not a general DLP suite, legal-advice product, or model-training platform. It is a pre-send safety layer intended to integrate with DLP, DMS, Office/browser surfaces, and identity gateways.
Junas is a security and compliance privacy-tools suite with one deterministic review and policy backend behind multiple activation surfaces. The FastAPI backend is the trust boundary for Junas deployments. It owns review input validation, tenant/auth checks, deterministic findings, policy decisions, rewrite actions, audit events, and privacy-safe observability. Adapters are not required to integrate Junas: direct HTTP/OpenAPI clients remain the baseline path and can integrate with this boundary without installing a UI adapter.
Adapters are workflow activation points. Supported targets such as Outlook Smart Alerts, browser GenAI capture, DMS hooks, and direct API clients should collect workflow context, call the backend contract, display the decision, and avoid storing raw content outside their runtime unless a documented policy allows it. Experimental surfaces such as the Word taskpane and desktop watcher are author-side or local fallback review until promoted.
Audience-specific surfaces:
| Audience | Current surfaces | Sell as |
|---|---|---|
| Developers and platform teams | FastAPI, OpenAPI, Python client, junas CLI |
Deterministic review, rewrite, redaction, approval, and audit APIs for internal workflows. |
| Security, compliance, and operators | Outlook Smart Alerts, Browser GenAI extension, DMS/API hooks, SIEM-safe telemetry, audit export; Word taskpane as experimental author-side review | Policy-controlled pre-send and pre-share review where controlled workflows can enforce completion. Word does not enforce save, export, print, share, email send, DMS upload, or repository check-in. |
| General public and evaluators | Hosted/local deterministic demo, synthetic visual redaction demo artifacts | A concrete demo of the privacy-review concept; screen/video redaction is demo-only, not endpoint enforcement. |
- Deterministic first: rules, jurisdiction packs, scoring, and policy decide the baseline before helpers run, giving regulated buyers inspectable evidence instead of a black-box verdict; see
ARCHITECTURE.md,docs/architecture.md, andsrc/junas/review/engine.py. - Backend trust boundary: adapters collect workflow context, but FastAPI owns auth, validation, findings, policy, rewrite actions, and audit events, so UI surfaces do not become parallel enforcement engines; see
docs/adr/0001-backend-first-adapters-second.mdanddocs/threat-model.md. - LLM strictly advisory and gated:
strictstays deterministic, while remote/helper paths require deployer and tenant opt-ins plus privacy-ledger evidence; seedocs/llm-governance.md,docs/running.md, andtest/test_llm_coverage_audit.py. - Deterministic-high non-suppression: helper layers route only eligible ambiguous cases, so deterministic-high findings stay in the review evidence path instead of being erased by LLM, public-evidence, adapter, or policy softening; see
src/junas/review/engine.py#L4317,test/test_source_verification.py, andtest/test_policy_engine.py. - Statute-cited findings: review output carries legal-basis codes and generated rationales for PII/MNPI findings, making the first response useful to counsel and compliance reviewers; see
docs/statutory-coverage.mdandtest/test_citations.py. - Privacy-gated external calls: optional provider calls are disabled by default, sanitized through PrivacyGuard, and recorded as privacy-ledger/SIEM evidence when used; see
src/junas/external/privacy_guard.py,docs/threat-model.md, andtest/test_siem_export.py. - Audit evidence by default: decisions, required actions, IDs, hashes/counts, SIEM events, and audit packs are first-class outputs so reviewers can reconstruct what happened without putting raw payloads in observability streams; see
docs/admin-security.md,test/test_siem_export.py, andtest/test_audit_pack_smoke.py.
Compact runtime spine; see ARCHITECTURE.md for the reviewer map and docs/architecture.md for the longer runtime overview.
flowchart LR
Adapters[Adapters / direct API<br/>Outlook, browser, DMS, clients] --> Boundary[FastAPI backend<br/>trust boundary]
Boundary --> Engine[Deterministic review engine<br/>PII + MNPI + citations]
Engine --> Policy[Policy decision<br/>allow / warn / block / approval / rewrite]
Policy --> Evidence[Actions + audit evidence<br/>redact / hold / approval / SIEM]
Boundary -. privacy-gated opt-in .-> PublicEvidence[Optional public evidence]
Boundary -. tenant + deployer gated .-> LLM[Optional LLM helpers]
PublicEvidence -. annotate ambiguous cases .-> Engine
LLM -. advisory only .-> Engine
| Surface | Maturity | Role | Evidence |
|---|---|---|---|
| API/client | core |
Baseline HTTP/OpenAPI integration path. | OpenAPI and backend contract tests. |
| Outlook Smart Alerts | supported-target |
First-class pre-send email review target. | test/test_adapter_smoke.py, test/test_outlook_manifest_validate.py. |
| Browser GenAI extension | supported-target |
First-class prompt review target for managed browser pilots. | test/test_adapter_smoke.py, test/test_browser_extension.py. |
| Word taskpane | experimental |
Document review surface, not send-time enforcement. | Fixture smoke in test/test_adapter_smoke.py. |
| Desktop watcher | experimental-local-fallback |
Opt-in local fallback for demos, offline review, and power users. | Local watcher tests in test/test_desktop_watch.py. |
Final enforced completion should run through Outlook Smart Alerts, DMS hooks, direct API, or another controlled workflow unless a Word enforcement path is implemented and promoted.
Browser GenAI screenshots: warn confirm and policy block. They use a synthetic chatgpt.com fixture with the real MV3 extension and local backend; see docs/integrations/genai-browser.md for the DOM-stability caveat.
Outlook Smart Alert renderings: allow, warn, block, and approval required. They render the real fixture strings from test/fixtures/outlook_smart_alert_messages.json; see docs/integrations/outlook.md for client-validation limits.
The desktop watcher is intentionally outside the primary Quick Start. The junas-watch console script remains installed for explicit opt-in file, folder, or clipboard review against a local daemon, but it is experimental-local-fallback, not production enforcement.
uv run junas-watch ./draft.txt --base-url http://127.0.0.1:8765
uv run junas-watch --watch-folder ./drop --once --base-url http://127.0.0.1:8765
uv run junas-watch --clipboard --once --base-url http://127.0.0.1:8765
uv run junas-watch --clipboard --once --copy-anonymized-clipboard --base-url http://127.0.0.1:8765
uv run junas --tui
./script/build_and_run.sh --verify
uv run junas displays list
uv run junas displays capture --display 1 --output-dir ./captures --dry-run
printf '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}\n' | uv run junas sidecar stdio
uv run junas redact ./recording.mov --output ./captures/recording-redacted.mp4 --box 0,0,240,120
uv run junas buffer prototype --frames-dir ./capture-frames --output-dir ./buffer-demo --dry-run --json
uv run junas obs prototype-source --frames-dir ./obs-input-frames --output-dir ./obs-prototype --dry-run --json
uv run junas mp4 from-redacted-frames --frames-dir ./redacted-frames --output ./captures/redacted-session.mp4 --dry-runSee docs/integrations/desktop-watcher.md for the security model and limitations. The AppleScript/Shortcuts wrapper for explicit clipboard redaction is documented in docs/integrations/macos-automation.md.
The macOS menu-bar shell is documented in docs/integrations/macos-menu-bar-shell.md.
The menu-bar sidecar protocol is documented in docs/integrations/menu-bar-sidecar-protocol.md.
Multi-display capture selection is documented in docs/integrations/multi-display-capture.md.
Offline video redaction is documented in docs/integrations/offline-video-redaction.md.
The recording-only time-buffer prototype is documented in docs/integrations/time-machine-buffer.md.
The OBS source-plugin evaluation is documented in docs/integrations/obs-source-plugin.md.
The direct MP4 sink is documented in docs/integrations/direct-mp4-sink.md; use it for already-redacted frame directories when a local file is preferable to OBS or a virtual camera.
Runtime:
GET /healthGET /readyGET /diagnosticsGET /metrics
Review and rewrite endpoints:
POST /reviewPOST /pseudonymizePOST /anonymizePOST /redactPOST /redact-piiPOST /hold-until-publicPOST /cite-public-sourcePOST /request-approvalPOST /safe-rewritePOST /reidentifyPOST /documents/scrub
Compatibility:
POST /classifyPOST /classify/batch
Review-session and local desktop support:
POST /review/{review_id}/decisionGET /review/{review_id}GET /local/pairing/statusPOST /local/pairing/startPOST /local/pairing/approvePOST /local/pairing/claim
Generated integration artifacts live in docs/api/:
Review without rewriting:
curl -X POST http://127.0.0.1:8000/review \
-H "Content-Type: application/json" \
-d '{
"text": "Project Raven will acquire GlobalTech for USD 2.5 billion before announcement.",
"source_jurisdiction": "SG",
"destination_jurisdiction": "US",
"document_type": "SPA"
}'Review and rewrite with irreversible anonymization:
curl -X POST http://127.0.0.1:8000/anonymize \
-H "Content-Type: application/json" \
-d '{
"text": "Dr Jane Tan, passport E1234567, will receive the memo.",
"source_jurisdiction": "SG",
"destination_jurisdiction": "EU"
}'Use the Python client:
from junas import JunasClient
with JunasClient("http://127.0.0.1:8000") as client:
result = client.classify(
text="Acme Corp is acquiring GlobalTech for $2.5 billion next quarter.",
entity_id="acme-corp",
include_offending_spans=True,
)
print(result.classification)
print(result.findings)Run included client examples:
python scripts/examples/sync_client_example.py \
"Acme Corp is acquiring GlobalTech for $2.5 billion next quarter." \
--include-offending-spans
python scripts/examples/async_client_example.py \
"Acme Corp is acquiring GlobalTech for $2.5 billion next quarter." \
--include-offending-spansRegenerate API examples from the live OpenAPI contract:
python3 scripts/export_openapi_examples.pyJunas has five main runtime pieces:
- The FastAPI backend in
src/junas/backend/exposes review, rewrite, document, auth, local pairing, observability, and audit endpoints. - The deterministic review engine in
src/junas/review/runs universal recognizers, jurisdiction TOML packs, MNPI evidence rules, citations, defined terms, document structure, and strictest-wins scoring. - The rewrite layer in
src/junas/anonymize/builds deterministic placeholders, reversible mappings, opaque redactions, and reidentification. - Privacy-gated external helpers in
src/junas/external/sanitize outbound queries and optionally fetch public evidence. - Advisory helpers in
src/junas/advisory/provide optional LLM adjudication, defined-term extraction, and coverage audit paths. These layers are advisory unless explicitly documented otherwise and cannot suppress deterministic-high findings.
Core flow:
flowchart TD
Client[Client / Desktop / Integration] --> API[FastAPI backend]
API --> Extract[Text and document extraction]
Extract --> Engine[Deterministic review engine]
Engine --> PII[PII recognizers]
Engine --> MNPI[MNPI evidence rules]
PII --> Score[Strictest-wins scoring]
MNPI --> Score
Score --> Response[Findings, scores, suggestions]
Response --> Rewrite{Rewrite requested}
Rewrite -->|pseudonymize| Map[Persist reversible mapping]
Rewrite -->|anonymize| Placeholders[No mapping retained]
Rewrite -->|redact| Opaque[Opaque markers]
Junas ships curated jurisdiction packs for:
🇸🇬 SG, 🇲🇾 MY, 🇮🇩 ID, 🇹🇭 TH, 🇵🇭 PH, 🇻🇳 VN, 🇭🇰 HK, 🇦🇺 AU, 🇯🇵 JP, 🇰🇷 KR, 🇺🇸 US, 🇬🇧 UK, 🇪🇺 EU, 🌏 SEA, 🇮🇳 IN, 🇨🇳 CN, 🇦🇪 AE, 🇸🇦 SA
Each pack lives under src/junas/review/jurisdictions_data/ and is mapped to statutory coverage in docs/statutory-coverage.md.
| Coverage family | Applies to | Examples |
|---|---|---|
| Universal PII | All jurisdiction modes | Email, phone, passport, bank account, DOB, age, postal address, IP address, MAC address, IMEI, named person, linkable internal ID, quasi-identifier cluster, special-category PII, minor data |
| Jurisdiction-specific PII | Curated TOML packs in src/junas/review/jurisdictions_data/ |
National IDs, tax IDs, company IDs, address formats, financial/account references, local legal references, registry references |
| Privacy events | Jurisdiction-resolved citation path | Cross-border transfer, consent withdrawal, data minimisation, safeguards, breach notification |
| Universal MNPI | All jurisdiction modes | Deal events, non-public markers, financial scalars, contingent language, tipping/selective disclosure, insider-list markers, information barriers, blackout windows, conjunctive MNPI |
| Sector/event MNPI | Evidence rules across supported packs | Cybersecurity incidents, ESG/climate events, digital-asset listing or protocol events, pharma events, financial-services events, energy/mining events, legal proceedings |
| Optional advisory enrichment | Server/audit-grade opt-in paths | Public evidence, LLM adjudication, defined-term extraction, coverage audit; advisory only, deterministic-high findings remain controlling |
| Optional secret rule packs | Local opt-in Gitleaks TOML import | Credential/API-token regexes from a local rule-pack file; no cloud dependency or provider calls |
The README keeps the jurisdiction table readable. The exhaustive detector-level tables live in docs/statutory-coverage.md, including universal PII rules and jurisdiction-specific recognizers.
Junas can import local Gitleaks TOML rule packs when JUNAS_GITLEAKS_RULE_PACKS
points to one or more files. The import is disabled by default, runs locally,
does not call Gitleaks, TruffleHog, or any cloud service, and bounds file size,
rule count, regex length, and findings per review. Secret matches surface as
high-severity redaction findings under EXTERNAL_SECRET_RULE_PACK.
See docs/secret-rule-packs.md for supported
fields, TruffleHog evaluation notes, and performance bounds.
Community rule-pack format, fixtures, and local smoke testing are documented in
docs/community-rule-packs.md. A seed pack
exists under rules/community/:
uv run junas rules test \
--gitleaks rules/community/gitleaks-acme-demo.toml \
--text-file rules/community/fixtures/acme-api-token.txtAccuracy and corpus notes:
- Generated detector accuracy disclosure:
docs/accuracy.md - Candidate corpus status:
docs/candidate_corpus_status.md - Committed evaluation reports:
reports/layer-attribution/ - Known limitations:
docs/known-limitations.md
Junas reduces review risk before content leaves a trusted workflow; it does not prevent every leak, replace legal judgment, or provide universal DLP/endpoint enforcement. Practical limits:
- Document extraction can degrade on unsupported or partially unreadable formats such as native
.msg,7z, macro-enabled Office files, signatures, forms, annotations, embedded files, and nested attachments; operators can set fail-closed modes when best-effort review is not acceptable. - Image OCR is optional, so image-only text is not reviewed unless OCR dependencies are enabled; small, low-contrast, rotated, or compressed text can still be missed by OCR.
- Browser and Office adapters depend on vendor runtimes, tenant deployment, DOM/editor structure, permissions, CORS, and client versions; they are workflow activation layers, not universal capture across every app or browser surface.
- Deterministic rules are strongest on committed PII/MNPI fixture coverage and statute-backed patterns; ambiguous context, novel formats, and public-evidence questions may still need reviewer judgment or explicitly enabled advisory layers.
- Public evidence and LLM helper paths are disabled by default; enabling them changes deployment risk and requires the opt-in, privacy, retention, and egress controls documented in the deployment guides.
See docs/known-limitations.md for the full limitations list.
Current evidence is in-domain regression evidence over committed fixtures, not a claim about general-world accuracy. docs/accuracy.md is generated from committed recall and precision locks and reports detector-level span evidence; for PII-style detector evaluation, Junas follows the Presidio guidance that recall often matters more than precision and uses F-beta=2 when a recall-weighted combined score is needed (Presidio evaluation, presidio-research).
The promoted strict candidate report is 20260608-strict-item70v2_strict_candidate_eval.json: 1,428 approved legal/cross-jurisdiction documents, 17,552 strict expected labels, strict recall 1.0000, and strict precision 0.9269. Treat this as an in-repo legal fixture benchmark and regression gate, not an independent market benchmark. docs/candidate_corpus_status.md tracks jurisdiction stage, approval state, and report links.
Independent PII/anonymization benchmarks such as TAB and ai4privacy are named here as future comparison targets only; no Junas score on those datasets is claimed until an eval report is committed. There is no public MNPI benchmark in this repo comparable to TAB or ai4privacy, so MNPI evidence currently comes from in-domain legal fixtures, statutory coverage, and review examples. Public-evidence matching and LLM adjudication accuracy are outside the deterministic detector locks.
junas-local is offline-default. It includes the deterministic engine, Presidio, spaCy, FastAPI, document extraction, local mappings, and packaging.
It must not require:
torch, transformers, sentence-transformers, redis, xgboost, scikit-learn, pandas, external HTTP
Build the desktop package:
uv sync --extra local --extra packaging
uv run python -m spacy download en_core_web_sm
uv run pyinstaller packaging/junas-local.spec
./dist/junas-local/junas-localjunas-server enables optional public evidence and LLM helper paths for approved tenants.
Public evidence:
JUNAS_PUBLIC_EVIDENCE_ENABLED=1 \
JUNAS_PUBLIC_EVIDENCE_PROVIDER=serper \
SERPER_API_KEY=... \
PIPELINE_LAYERS=public_evidence \
uv run uvicorn junas.backend.main:app --host 0.0.0.0 --port 8000LLM adjudication with remote structured tokens:
JUNAS_LLM_ENABLED=1 \
JUNAS_LLM_PROVIDER=openai \
JUNAS_LLM_API_KEY=... \
JUNAS_LLM_BASE_URL=https://api.openai.com/v1 \
JUNAS_LLM_ALLOW_REMOTE_BASE_URL=1 \
JUNAS_LLM_TENANT_OPT_IN_OPENAI=1 \
JUNAS_LLM_INPUT_MODE=structured_tokens \
PIPELINE_LAYERS=llm_adjudicator \
uv run uvicorn junas.backend.main:app --host 0.0.0.0 --port 8000Remote raw text requires an additional explicit opt-in:
JUNAS_LLM_ALLOW_REMOTE_RAW_TEXT=1
review_profile=strict never invokes LLM helper layers.
Local OCR-region LLM prototype:
JUNAS_LOCAL_OCR_LLM_ENABLED=1 \
JUNAS_LOCAL_OCR_LLM_MODEL=<local-ollama-model> \
uv run junas ocr classify-region --text "AK1A0CRNO1SE" --confidence 0.41 --jsonThis prototype is local-only, loopback-gated, advisory, and off by default. It
does not add default dependencies or change strict review. See
docs/local-ocr-llm.md.
docker compose up --build
curl http://localhost:8000/readyProduction Docker baseline:
docker compose -f docker-compose.production.example.yml up --build
curl -fsS http://localhost:8000/readyThis example turns on tenant auth, policy config, journal keys, no body logs, and readiness checks. Replace the sample files under deploy/docker/ before use.
Managed LLM deployment:
JUNAS_LLM_API_KEY=... \
JUNAS_LLM_TENANT_OPT_IN_OPENAI=1 \
SERPER_API_KEY=... \
docker compose -f docker-compose.yml -f docker-compose.managed-llm.yml up --buildINTEGRATIONS.md: root index for direct API, Outlook, browser, Word, desktop, DMS, and future surfaces.ARCHITECTURE.md: reviewer-facing request lifecycle, trust boundary, and invariants.BENCHMARKS.md: reproducible latency, SLO, and corpus benchmark evidence.CHANGELOG.md: tagged install-release notes and artifact links.CONTRIBUTING.md: development setup, verification commands, invariants, and good first issues.SECURITY.md: private reporting path and security-scope expectations.docs/roadmap.md: Now/Next/Later issue triage and promotion gates.docs/release-process.md: release tag convention and artifact checklist.docs/distribution.md: current wheel/sdist path plus Cargo, Nix, Homebrew, and DMG status.docs/blog/engineering-pre-send-review.md: draft technical companion post backed by benchmark artifacts.docs/architecture.md: runtime architecture and core flow.docs/statutory-coverage.md: detector-to-statute coverage map.docs/known-limitations.md: unsupported ingest, deployment, and legal/accuracy caveats.docs/running.md: launch commands and optional layer setup.docs/install.md: desktop, browser extension, Office add-in, and server install flow.docs/admin-security.md: tenancy, API keys, JWT, SIEM, and local pairing controls.docs/threat-model.md: data flow, trust boundaries, threats, controls, and residual risk.docs/deployment-hardening.md: production filesystem, transport, secrets, Kubernetes, SIEM guidance, and deployment-mode comparison.docs/mapping-store-hardening.md: key-gated mapping encryption, retention, erasure, and mapping-store controls.docs/llm-governance.md: LLM promotion, privacy evaluation, and invariant gates.docs/schema.md: API and artifact contracts.docs/api/: Postman, cURL, and Python client integration artifacts.docs/faq/developer.md: endpoint-choice FAQ for review, rewrite, scrub, reidentify, and classify flows.docs/faq/operator.md: DLP/CASB/endpoint-control coexistence FAQ for operators.
Install development dependencies:
uv sync --extra dev
uv run python -m spacy download en_core_web_smRun lint and focused runtime checks:
uv run ruff check
./scripts/verify_runtime.shRun the full test suite:
uv run pytestRun recall and generated-doc gates:
uv run python scripts/recall_gate.py
uv run python scripts/generate_accuracy_doc.py --checkRun latency checks:
./scripts/benchmark_latency_corpus.sh
uv run python scripts/check_latency_slo.py --write-reportCandidate and audit tooling:
uv run python scripts/run_layer_attribution_eval.py
uv run python scripts/export_audit_pack.py "$REVIEW_ID" --output ./out/audit.zip
uv run python scripts/verify_audit_pack.py ./out/audit.zip
uv run python scripts/verify_journal.pyTraining and optional local-student LLM work lives in training/distillation/. It is not part of the offline-default local SKU.
Use CONTRIBUTING.md for setup, verification commands, deterministic-local invariants, and scoped good first issues.
Version source: Python package metadata in pyproject.toml is currently 0.1.0. Current install release: v0.1.0, with junas-0.1.0-py3-none-any.whl and junas-0.1.0.tar.gz. The top CI badge points at .github/workflows/ci.yml. The readme-demo-assets-2026-06-30 release is media-only and not an install-version badge. Cargo, Nix, Homebrew, and signed-DMG status lives in docs/distribution.md.
Build the macOS desktop bundle:
uv sync --extra local --extra packaging
uv run python -m spacy download en_core_web_sm
./scripts/package_macos_desktop.shOptional release signing:
JUNAS_CODESIGN_IDENTITY="Developer ID Application: Example Pte Ltd (TEAMID)" \
JUNAS_NOTARYTOOL_PROFILE=junas-notary \
JUNAS_RELEASE_SIGNING_REQUIRED=1 \
./scripts/package_macos_desktop.shRelease signing uses the project-level Developer ID policy in docs/macos-signing-credentials.md.
Signed DMG packaging and stock-Mac verification gates are documented in docs/macos-dmg-release.md.
Homebrew tap naming and cask publication gates are documented in docs/homebrew-cask.md.
Optional admin-controlled LaunchAgent lifecycle; not a default developer quickstart:
packaging/macos/install.sh
packaging/macos/update.sh
packaging/macos/uninstall.shPackage browser extension:
./scripts/package_browser_extension.shPackage surfaces:
integrations/browser_extension/: MV3 browser thin client.integrations/outlook_addin/: Outlook taskpane and Smart Alerts pre-send hook.integrations/word_addin/: Word taskpane review surface.packaging/macos/: LaunchAgent install, update, uninstall scripts.packaging/windows/: Windows packaging notes; Windows desktop packaging is not shipped by default.
No screenshot assets are currently tracked for README embedding beyond the logo.
Useful screenshots to add under asset/screenshots/:
- FastAPI
/docsshowing the active Junas API surface. - Example
/reviewor/pseudonymizeresponse with sensitive values redacted. - macOS local daemon or tray/terminal run state.
- Browser extension pre-send review surface.
- Outlook or Word add-in review surface.
- Audit-pack or diagnostics view if there is a stable UI for it.
Once those files exist, this section can embed them with relative links.
No LICENSE file is currently checked in.