# Prompt Guard company identity and content inspection

These capabilities extend the **customer-hosted Prompt Guard gateway**. They do not change the hosted subscription endpoint, its text-only limits, or its billing. Installing the gateway, connecting a company's identity provider, mounting its certificates and choosing its policies are customer setup steps.

## Company sign-in and automatic employee provisioning

1. Download every runtime file from deployment.html, including enterprise-directory.mjs, enterprise-oidc.mjs, content-inspection.mjs, inspection-service.mjs and extract-content.py. Follow managed-gateway.md for the gateway and separate administrative audit keys and TLS certificates.
2. Run `node initialize-enterprise.mjs NEW_DIRECTORY`. This creates an empty directory, a 90-day provisioning credential, a one-time token file and an OIDC configuration example. Do not publish that directory. Move `directory.json` into the writable identity directory; store the OIDC and SCIM credential configuration in the operator-owned read-only secrets directory. Only the management service may write the identity and policy directories. Gateway mounts of both directories must be read-only and must include the `.edit-lock` barriers.
3. Register an OpenID Connect **confidential web application** in the company's identity provider. Use authorization-code flow, client-secret POST authentication, RS256 ID tokens and PKCE S256. The exact redirect URI is `https://YOUR_ADMIN_HOST:8444/auth/callback` (or the configured HTTPS origin with `/auth/callback`). Copy its tenant-specific issuer, authorization endpoint, token endpoint and JWKS URL into `oidc-config.json`. All endpoints must be HTTPS; redirects are rejected. Register the exact externally reachable origin, including the port. Use the application's client ID/secret. No dynamic discovery or token-provided key URLs are trusted.
4. Configure SCIM 2.0 provisioning with base URL `https://YOUR_ADMIN_HOST:8444/scim/v2` and the contents of `scim.token` as its bearer token. Expose only the necessary TLS route through the customer's existing ingress/network controls. For IdPs supporting client certificates, add `certificateSha256` to `scim-credential.json` to require that certificate as well. The token file itself is not mounted on the service. Expired/removed credentials fail closed and are rechecked after request intake. Rotate tokens through your secret-management process before expiry.
5. Map each SCIM user's **externalId to the exact signed OIDC subject** used by this application. The default is `sub`, never email or display name. For a tenant-specific Microsoft identity provider, `subjectClaim: "oid"` is also supported when SCIM externalId is mapped to that same object ID. Do not use a shared/multi-tenant issuer. Subject bindings are immutable: delete and recreate a resource for a different subject. Recreated users receive new IDs and do not inherit old gateway credentials.
6. Provision users and groups. Users, Groups, filtered list/read, create, replace, supported PATCH operations and delete are supported. Query filters are equality on userName, externalId or group displayName; pagination is bounded to 500 results. User patches support active/userName and an unchanged externalId. Group patches support displayName and member additions, replacement and removal. Bulk, password changes, arbitrary filters/extensions and nested groups are rejected, not silently applied. Optional name/email/displayName user profile fields are accepted but not stored or used for authorization.
7. Using a certificate-authenticated break-glass administrator, view the directory in the console. Put the resulting **group IDs**, not display names, in `roles.admin` and `roles.auditor` in the OIDC configuration; restart management after changing this root/operator-owned configuration. An empty role map grants nobody SSO console access. SCIM-provisioned group membership grants the configured role. Protect the provisioning token as an administrative credential.
8. Set GUARD_OIDC_CONFIG_FILE, GUARD_SCIM_CREDENTIAL_FILE and GUARD_DIRECTORY_FILE on management. Set GUARD_DIRECTORY_FILE on the data gateway too. In directory mode **every** actor requires a valid `directoryUserId`, including service identities. Bind that field to the provisioned user ID; the existing certificate and expiring bearer credential remain mandatory for gateway requests. Missing configuration for a directory-bound actor rejects access.
9. Use a SCIM group's ID as a policy group's ID to apply its restrictions automatically to member actors. These rules combine with explicit actor groups and organization policy: none can weaken organization restrictions. Membership changes or deactivation during extraction or durable acceptance cancel the request before upstream forwarding.

Company-login browser sessions need no client certificate. Break-glass administrators continue to require their allowlisted, unexpired certificate. Workload TLS requirements remain unchanged. Sessions last at most one hour and no longer than the ID token. Directory access and current roles are checked on every administrative request and again before policy writes. Deactivation, group removal and directory errors deny access immediately when the shared file changes. Sessions are in memory, are not shared across replicas and disappear on restart. Logout ends the Prompt Guard session; it does not sign the user out of their identity provider.

The existing signed administrative journal records directory-change hashes and sign-in/out actor IDs without credentials or token bodies. A failed directory commit leaves its durable edit barrier in place; login and data requests fail closed across restart. Follow the same stop/verify/reconcile/archive procedure as policy recovery, using the directory requested/committed hashes. Never remove a barrier while a writer runs or without reconciling the journal.

## Local files, image text and audio transcription

Build `Enterprise.Dockerfile` instead of the minimal text-only image. It includes Python, Poppler, Tesseract English OCR, FFmpeg and faster-whisper. No paid speech or OCR API is used. Download a reviewed Whisper model **before deployment** and mount it read-only at `/models/whisper` on the **inspection worker only**:

```sh
python -m pip install -r content-requirements.txt
python -c "from faster_whisper.utils import download_model; download_model('tiny.en', revision='0d3d19a32d3338f10357c0889762bd8d64bbdeba', output_dir='./models/whisper')"
```

`tiny.en` is the tested reference model, not a claim of comprehensive speech recognition. Evaluate representative recordings and use an appropriate reviewed English model for your deployment. Runtime transcription uses local files only and offline model settings. Model downloads are a build/setup operation; a missing model rejects audio inspection.

Use the supplied enterprise-compose.yaml as a bounded deployment template. Replace image placeholders with a reviewed digest. Create writable request-audit/admin-audit directories owned by UID/GID 10001. Policy and identity directories must be writable by management; secrets and models must only be readable by the appropriate process. Separate gateway provider secrets from management identity secrets. Remove environment entries and mounts for unused providers. Administration is published only on loopback by default: configure your existing trusted TLS ingress or tunnel for browser callbacks and IdP provisioning, with the certificate SAN and configured origin matching. Keep workload and management networks separate. Attach protected workload containers **only** to the internal protected_workloads network; adding another network or privileged host access defeats that boundary. Check direct provider access is denied from each protected workload before rollout. The template does not manage employee laptops or other networks.

Enable `GUARD_CONTENT_INSPECTION=enabled` and set `GUARD_INSPECTION_SOCKET=/inspection/extractor.sock` on the gateway. The separate inspection service runs `node inspection-service.mjs` with GUARD_PYTHON and GUARD_WHISPER_MODEL_DIR. The enterprise image supplies their default paths. Gateway startup probes the Unix-socket worker and refuses to listen unless it responds healthy; there is no local-parser fallback. Overload returns 429, worker/IPC unavailability returns 503, and actual extraction rejection returns 422, so clients can distinguish retryable availability from unsupported content. Temporary extraction occurs only inside the isolated worker. It uses a private directory on `/tmp`, removed after processing; the compose template mounts `/tmp` as ephemeral memory storage. The parser runs as UID 10002 in a **separate container with network_mode: none**, no provider/TLS/audit/identity mounts, no capabilities and a read-only filesystem. Its only mounts are the read-only speech model and the shared Unix-socket directory; it cannot access the gateway filesystem or network. The gateway mounts the socket directory read-only and connects using group permission 0660. Do not attach a network or mount credentials into the worker. Parser subprocesses also receive a minimal environment. They have CPU/file/descriptor/address-space limits, bounded output, a 110-second process-group deadline and at most two concurrent extractions. If the worker crashes and leaves a stale socket, stop it and confirm no worker remains before removing the stale socket; never remove a live socket. Keep the container memory/PID limits and patched parser dependencies. Runtime has no automatic model download or remote attachment fetch. Original attachments are never sent upstream, persisted in audit, or returned to clients.

Supported inputs:

| Kind | MIME types and limits |
|---|---|
| Text | UTF-8 text/plain, text/csv, application/json |
| Documents | PDF, up to 10 pages, both selectable text and page OCR; DOCX text and embedded image OCR |
| Images | PNG/JPEG, one frame, at most 12 million pixels, English OCR |
| Audio | WAV, MP3, M4A, FLAC, Ogg; one audio stream, at most 60 seconds, English transcription |

Up to four attachments, 4 MiB combined decoded bytes, 6 MB JSON body and 16 KiB combined extracted/prompt text are accepted. Encrypted PDFs, document external relationships/macros/embedded executables, unsupported formats, empty extraction, low-confidence recognized words/transcript segments and parser failures are rejected. Nothing is forwarded after an extraction failure. Native Anthropic/Gemini binary content blocks remain rejected; submit supported attachments through the common request format below.

To inspect without making a provider request:

```json
POST /v1/inspect
{
  "messages": [],
  "attachments": [{"mimeType":"text/plain","data":"cGVyc29uQGV4YW1wbGUuY29t"}]
}
```

Use the existing client certificate and bearer credential. The response is blocked (422), or contains permitted/redacted text in `messages`, action, detector counts and request ID. For inspection and AI forwarding together, send the same attachments field alongside the usual provider/model/messages fields to `/v1/chat/completions`. Only sanitized extracted text is forwarded; the model does not receive the original image, file or audio. Authentication, employee access, organization/group policies, audit durability, quotas and provider scopes still apply. Never automatically retry an uncertain provider request.

OCR/transcription inspect recognized text, not every visual detail, voice characteristic or hidden encoding. A clear but incorrectly recognized word may evade pattern detection; low-confidence rejection cannot prove correctness. This is not malware scanning, semantic scene analysis, comprehensive PHI detection or a compliance certification. Those recognition limits must remain visible to customers.

## Acceptance checks

Run the utility tests, including enterprise-identity.test.mjs, content-inspection.test.mjs and content-audio.test.mjs. The audio test uses an actual local Whisper model and a synthetic FFmpeg voice. Also verify on the company's actual IdP: login, wrong-group denial, active session role downgrade, user deactivation, SCIM token expiry and subject mapping. Confirm deactivation blocks an existing gateway credential before forwarding. Test a representative document/image/audio canary under both block and redact policies, then verify original bytes and text do not appear in provider payloads or signed metadata. No real customer identity tenant or network can be certified by synthetic tests.
