Skip to content

Workspace Settings

A workspace setting is one administrative switch that changes how Logrite treats a whole workspace: how AI coding sessions are recorded and checked, what happens to a log line between a collector and the index, what a new collector collects, and what reaches the bell. There are 29 keys in five groups — coding.*, logging.*, ingest.*, collector.defaults.* and notify.*.

  • The catalogue is code, not data. Every key, its type, default and bounds live in the static WorkspaceSettingCatalog (backend, service/settings/). The ingest shim, the AI coding policy, the collector binding and the Settings hub read keys by name, so a key is a contract: adding one is a code change, and keys are never renamed (a rename would silently reset every workspace that changed the old one).
  • The table holds only what an admin changed. workspace_setting (migration mirror 2026-10-workspace-settings.sql) has one row per workspace per key: workspace_id, setting_key (VARCHAR(96)), value_json (the JSON of an already-validated value), updated_by, updated_at, UNIQUE (workspace_id, setting_key). No row = the catalogue default, so a new key never needs a data migration.
  • Reads are cached for 30 s per workspace. A read is the catalogue defaults overlaid with the stored values. A write evicts the cache immediately and again after commit. Consumers that cache on top (the shim’s 15 s binding cache, the coding policy’s 60 s cache) add their own delay — see How long a change takes to apply.
  • A stored value the current catalogue refuses (a range that was later tightened, or a key a later build dropped) reads back as the default and logs a warning; it is never handed to a consumer.
MethodPathWhoBody / answer
GET/api/v1/workspaces/{workspaceId}/settingsAny workspace member — session JWT or a Logrite API key (lgp_live_…){workspaceId, settings, catalogue}
PATCH/api/v1/workspaces/{workspaceId}/settingsAdmin or OwnerBody: a flat partial map {"<key>": value, …}. Answer: same shape as GET, with the new values

A non-member gets 404 workspace not found (or 403 where LOGRITE_CROSS_TENANT_NOT_FOUND=false). A member below Admin gets 403 changing workspace settings requires workspace admin — the role is checked before any key is looked at, so an outsider cannot probe which keys exist from the 400s.

Response. settings holds every key (stored value, else default). catalogue describes every key as {key, type, default, min?, max?, values?, maxItems?, maxLength?}; type is one of bool, int, enum, string, list. Read the catalogue before writing — it is what the Settings hub uses for its bounds.

Terminal window
curl -s "https://leapfrogapi.deployd.io/api/v1/workspaces/$WORKSPACE_ID/settings" \
-H "Authorization: Bearer $LOGRITE_API_KEY"
# {"workspaceId":3103,
# "settings":{"coding.enabled":true,"coding.capture":"findings",…,"notify.coding.bell":true},
# "catalogue":[{"key":"coding.enabled","type":"bool","default":true},
# {"key":"coding.capture","type":"enum","default":"findings","values":["metadata","findings","extended"]},
# {"key":"coding.retentionDays","type":"int","default":30,"min":7,"max":90}, …]}
Terminal window
curl -s -X PATCH "https://leapfrogapi.deployd.io/api/v1/workspaces/$WORKSPACE_ID/settings" \
-H "Authorization: Bearer $LOGRITE_API_KEY" -H "Content-Type: application/json" \
-d '{"ingest.sampling.enabled": true, "ingest.sampling.percent": 25, "coding.capture": null}'

PATCH semantics.

  • All or nothing. Every key in the body is validated before any is written; one bad key refuses the whole request and nothing is stored.
  • null resets a key to its default (the stored row is deleted). In the example above coding.capture goes back to findings.
  • Values are normalised before storage: strings and list items are trimmed; enum values and list items from a fixed set match case-insensitively and are stored in the catalogue’s own spelling ("error" → "ERROR"); list items are de-duplicated; a whole number sent as 25.0 is accepted, a fraction is not.
  • An empty body is a no-op that answers the current values.
  • Each successful PATCH writes one governance-audit row, action settings.update, with the actor’s email and {"keys": […]} — the keys changed, not their values.
StatusBodyWhen
400{"error":"unknown_setting","key":"coding.foo"}The key is not in the catalogue
400{"error":"invalid_setting","key":"ingest.sampling.percent","rule":"must be a whole number between 1 and 100"}The value breaks the key’s rule
403—Caller is a member but not Admin/Owner (PATCH only)
404—Caller is not a member of the workspace

The rule strings the backend answers with:

  • must be true or false
  • must be a whole number between <min> and <max>
  • must be one of: … / every item must be one of: …
  • must be a string / must be a list of strings / every item must be a non-empty string
  • at most <n> items
  • must be at most 64 characters / every item must be at most 64 characters
  • must be a field name: a letter or _ followed by letters, digits, _ . or - (also with the every item prefix)

The “Read by” column names the code that acts on the key. Defaults are what a workspace that never changed the key gets.

Read by the Claude Code plugin through the AI coding policy (GET {mcpUrl}/coding/policy, which carries the coding.* and logging.* values; the plugin caches it and uses built-in copies of these defaults until a policy has been fetched), and by the backend where noted.

KeyTypeDefaultAllowedWhat it does / read by
coding.enabledbooltrue—Master switch for recording. MCP server coding ingest: when off, POST /coding/events answers 202 {"accepted":0,"disabled":true} and stores nothing. Plugin: does not send turn events or commit-scan events when off; it still checks code locally
coding.captureenumfindingsmetadata, findings, extendedWhat is recorded per finding. MCP server coding ingest enforces it whatever the plugin sends: metadata drops each finding’s message, snippet and path (a pathHash is kept). extended currently records the same as findings (300-character messages, 200-character masked snippets). Shown on the AI Coding issue detail as captureLevel
coding.retentionDaysint307–90How long AI coding session data is kept. Backend CodingRetentionJob (cron 0 30 3 * * *) deletes coding-events-<ws> events and stored evidence (masked snippets, paths) older than this; issue rows and their counts, mute and fixed state are kept
coding.healbooltrue—Plugin Stop hook: hand the agent the issues in the files it changed and ask it to fix them before it stops. Never blocks
coding.healRoundsint10–2Plugin: how many times one turn can be sent back (0 = never). Never while the Stop hook is already active
coding.healMinSeverityenummediumlow, medium, high, criticalPlugin: issues below this are recorded but not sent back to the agent
coding.precommitbooltrue—Plugin pre-commit hook (installed by /logrite:init only when the developer agrees): when off, the hook does not check. It only warns — the commit always goes through
coding.scan.compliancebooltrue—Backend coding policy includes the workspace’s compliance-framework rules only when on; the plugin applies them to lines the agent adds
coding.scan.loggingbooltrue—Policy includes the logging-standard rules (credential or PII in a log call, missing correlation field) only when on
coding.scan.businessbooltrue—Policy includes the workspace’s business rules on the AI coding plane only when on
coding.notifyMinSeverityenumhighlow, medium, high, criticalBackend CodingIssueNotifier: a new or returning AI coding issue below this severity is announced neither on Discord nor on the bell

logging.* — logging standards for AI-written code

Section titled “logging.* — logging standards for AI-written code”
KeyTypeDefaultAllowedWhat it does / read by
logging.correlationFieldstring"" (not required)field name, ≤ 64 charsBackend coding policy builds the “log statement omits the required correlation field” rule from it (e.g. traceId). Empty = no such rule
logging.piiFieldslistemail, ssn, password, phone, dob, cardNumberfield names, ≤ 50 items, each ≤ 64 charsPolicy’s “log statement names a person” rule; the plugin also uses the list to mask those fields’ values in finding snippets. When an effective AI-coding policy of the workspace includes HIPAA, the policy appends fullName, full_name, birthDate, birth_date, dateOfBirth, date_of_birth, mrn (2026-10-09; the stored value is unchanged)

ingest.* — ingest-time redaction and sampling

Section titled “ingest.* — ingest-time redaction and sampling”

Read by the ingest shim (POST /ingest) on every line from a collector agent or the ingest endpoint, via the agent resolve binding’s ingestPolicy. Not applied to OTLP/Data Prepper or the Bulk API. Full behaviour: Ingest-time redaction and sampling.

KeyTypeDefaultAllowedWhat it does
ingest.redaction.enabledboolfalse—Mask matching values before the line is stored; a changed line carries redacted: true
ingest.redaction.kindslistevery kind except longDigitsurlCredential, credentialPair, email, ssn, mrn, card, iban, phone, dob, secretKey, opaqueToken, longDigits (≤ 12 items)Which value patterns are masked. longDigits (9+ digit numbers) is off by default because it also masks order and trace IDs. mrn, phone and dob were added 2026-10-09 (patterns in Relay compliance → Redaction kinds)
ingest.redaction.fieldslistpassword, accessToken, refreshToken, otp, pin, last4, ssn, ccNumber, ccNbr, creditCardNumber, creditCardNbrfield names, ≤ 50 items, each ≤ 64 charsField names whose following value is masked (password=hunter2 → password=***)
ingest.sampling.enabledboolfalse—Store only a share of lines; kept lines carry sampleRate
ingest.sampling.percentint1001–100Share of lines kept at levels not in alwaysKeep
ingest.sampling.alwaysKeeplistFATAL, ERROR, WARNFATAL, ERROR, WARN, INFO, DEBUG, TRACE (≤ 6 items)Levels never sampled out

warden.* and cortex.* — privacy switches (2026-10-09)

Section titled “warden.* and cortex.* — privacy switches (2026-10-09)”

Admin-written. Every change to one of these six keys writes the settings.update GovernanceAudit row with details.privacyChanges naming each key with its old and new value, so turning masking off can be found later. Behaviour: AI Warden → Redaction switches and AI service → Cortex masking.

KeyTypeDefaultAllowedWhat it does / read by
warden.redaction.enabledbooltrue—Relay: false stores and shows Warden text as sent — previews, raw body, tool-call timeline, block message, compliance snippets, judge reasons. Detection and verdicts are unaffected
warden.redaction.kindslistevery kind except longDigitssame kinds as ingest.redaction.kindsKinds the relay masks. The raw body masks only the credential kinds (urlCredential, credentialPair, secretKey, opaqueToken) that are listed
warden.redaction.fieldslistsame as ingest.redaction.fieldsfield names, ≤ 50 itemsField names whose value the relay masks
warden.sensitiveRawCaptureboolfalse—“Keep the raw text of requests blocked for personal or health data. Turn on only when your model runs inside your own network.” When false, rows blocked or flagged for PHI/PII keep no raw text
cortex.redactionenumautoauto, on, offCortex: mask identifiers in answers. auto masks when HIPAA is enabled in the workspace (a policy that is not Off holds it, or a scan profile uses it)
cortex.redaction.kindslistallemail, ssn, mrn, card, iban, phone, dobWhich identifiers Cortex masks when masking is on

The relay reads the first four through the relay-key binding (redaction {enabled, kinds, fields, patterns} and sensitiveRawCapture); a binding without the block (older backend or cached binding) keeps the previous fixed masks.

collector.defaults.* — what a new collector collects

Section titled “collector.defaults.* — what a new collector collects”

Read by the backend when a collector is created (POST /api/v1/agents): any capability or interval the request leaves out (null) takes these values, and the New Collector Agent modal pre-fills its fields from them (fields you already edited are left alone). Existing collectors are not changed by editing a default — use Apply to existing collectors (POST /api/v1/agents/apply-defaults, see Collector agents → Live config at check-in).

KeyTypeDefaultAllowedCapability
collector.defaults.intervalMinutesint151–1440Check-in / ship interval (minutes)
collector.defaults.heartbeatbooltrue—Heartbeat each cycle
collector.defaults.systemDetailsbooltrue—System details (system_metrics host doc)
collector.defaults.journaldboolfalse—systemd journal
collector.defaults.varlogboolfalse—/var/log files
collector.defaults.dockerboolfalse—Docker containers
collector.defaults.k8sboolfalse—Kubernetes pods
collector.defaults.syslogboolfalse—Syslog receiver
KeyTypeDefaultWhat it does / read by
notify.warden.bellbooltrueFrontend notification sync: when off, AI Warden blocked/flagged requests are not added to the bell. Evaluated in each browser; an unreadable store counts as on
notify.coding.bellbooltrueBackend CodingIssueNotifier: when off, new or returning AI coding issues are not posted to the bell (Discord is unaffected; coding.notifyMinSeverity gates both)

gatekeeper.* — the pull-request gate (2026-10-15)

Section titled “gatekeeper.* — the pull-request gate (2026-10-15)”
KeyTypeDefaultAllowedWhat it does / read by
gatekeeper.coverageThresholdint800–100Backend GatekeeperThreshold: the log-coverage threshold a Gatekeeper check is measured against when the request sends none. Precedence: the request’s logCoverageThreshold → a stored workspace row (the workspace of the latest scan’s project; thresholdSource: "workspace") → the server property. Edited (Admin+) in Rules & Policies → Where rules apply → Code scans & log generation (“Pull-request gate”)
ConsumerDelay after a PATCH
Settings hub, workspace_settings getImmediate (the writer’s cache is evicted)
Ingest shim (ingest.*)Up to the shim’s agent-binding cache, 15 s (SHIM_TOKEN_TTL_MS), plus up to 30 s on a backend instance that did not serve the PATCH
Collectors (collector.defaults.*)Only new collectors, or existing ones after Apply to existing collectors — each picks it up at its next check-in
Claude Code plugin (coding.*, logging.*)From the next session; the policy endpoint caches 60 s per workspace

The 30 s settings cache is per backend instance; only the instance that served the PATCH evicts its copy.

Four tabs in Settings read and write these keys (/settings/aiCoding, /settings/logIngestion, /settings/privacy, /settings/notifications). Every member can open them and see what is in effect; only an Admin or Owner can change a switch — others see “Only a workspace admin can change these settings. You can see what is in effect.” Every switch is the shared LogriteSwitch control, and each change is one PATCH.

AI coding (aiCoding)

CardAnchorKeys
Recording#setting-ai-coding-recordingcoding.enabled (“Record AI coding sessions”), coding.capture (three side-by-side cards: Metadata only / Masked findings / Extended, each listing what is and is not recorded), coding.retentionDays (“Keep sessions for”)
Fixing in-session#setting-ai-coding-healcoding.heal, coding.healRounds (Never / Once / Twice), coding.healMinSeverity
Commit check#setting-ai-coding-precommitcoding.precommit (“Warn at commit”)
What to check#setting-ai-coding-checkscoding.scan.compliance, coding.scan.logging, coding.scan.business
Logging standards#setting-ai-coding-logginglogging.correlationField, logging.piiFields
Privacy#setting-ai-coding-privacyRead-only: what is never recorded, and the per-repository opt-out ("recordSessions": false)
Recording tokens#setting-ai-coding-tokensNot a setting. Lists the workspace’s write-only lgsi_live_ tokens that /logrite:init mints — one per workspace, shared by every repository on a machine (2026-10-09; earlier plugin versions minted one per repository) — (label, masked token lgsi_live_… + last four, created by, created, last used, Active/Revoked) and revokes them; a workspace admin or the token’s creator may revoke. The card says a revoked token “stops working at once”; in practice the MCP server caches a valid token for up to 60 s, so the plugin stops at its first flush after that. Recorded sessions are kept — see AI Coding → the session-ingest token
Setup#setting-ai-coding-setupRead-only: the plugin install one-liner and /logrite:init

Log ingestion (logIngestion)

CardAnchorKeys
Redaction#setting-ingest-redactioningest.redaction.enabled (“Redact before storing”), one switch per kind (ingest.redaction.kinds, with an example of what each kind masks), ingest.redaction.fields. Footnote: redaction and sampling apply to collectors and the ingest endpoint, not to OTLP exports
Sampling#setting-ingest-samplingingest.sampling.enabled, ingest.sampling.percent (“Keep N% of lines at the other levels”), one switch per level (ingest.sampling.alwaysKeep)
Retention#setting-ingest-retentionNot a workspace setting: the M-26-14 retention policy (hot/warm/cold tiers, searchable/retrievable windows), the same form as the M-26-14 page, saved through PUT /api/v1/retention/policy. Maintainer or above may save it
Collector defaults#setting-ingest-collector-defaultscollector.defaults.intervalMinutes (“Check-in interval”) and one switch per capability, plus the Apply to existing collectors button (confirm dialog “Apply these defaults to every collector?”)

Privacy (privacy, 2026-10-09)

CardAnchorKeys
AI Warden redaction#setting-privacy-warden-redactionwarden.redaction.enabled (“Mask what AI Warden stores”), one switch per kind (warden.redaction.kinds, now including MRN, phone and date of birth), warden.redaction.fields. Applies to requests captured after the change
Raw text of requests blocked for personal data#setting-privacy-sensitive-rawwarden.sensitiveRawCapture (“Keep the raw text”)
Cortex answers#setting-privacy-cortexcortex.redaction (row “Mask identifiers”, Auto / On / Off — “Auto masks identifiers in workspaces whose policies use HIPAA.”), cortex.redaction.kinds. A line points to Log ingestion → Redaction for stored logs

Notifications (notifications)

CardAnchorWhat
In-app notifications#setting-notifications-in-appnotify.warden.bell (“AI Warden”), notify.coding.bell (“AI coding”), coding.notifyMinSeverity (“AI coding: minimum severity — for the bell and Discord alike”)
Discord#setting-notifications-discordThe Discord channel card, moved here from Settings → Integrations. Not a workspace setting; Maintainer or above may manage it
Email preferences#setting-email-preferencesMoved here from Settings → General. Per-user, not per-workspace (saved through the user-settings API): Log analysis report, Critical issues alert, Code generation success, Welcome email. Security emails (verification, password reset, sign-in codes, new-device alerts) are always sent

Settings → Connections (MCP / OAuth connections) lost its Workspace column (it always showed the current workspace) and merged Created and Last used into one Activity column (“Created …” over “Last used …” / “Never used”).

All of these cards are reachable from the settings search box.

The MCP server exposes the store as one grouped tool in the Workspace family. The workspace is always the one the credential belongs to — there is no workspace argument, so a write cannot be aimed at a workspace the model merely knows the number of.

ActionScopeArgumentsBackend call
getworkspace:readnoneGET /api/v1/workspaces/{ws}/settings — every value plus the catalogue
setsettings:managesettings: a flat map, e.g. {"coding.capture": "metadata", "ingest.sampling.percent": 25}PATCH the same path; still needs the Admin or Owner role on the backend

set with a missing or empty settings map is refused before any call. An unknown key or a bad value refuses the whole change and names the key (the backend’s 400).

The OAuth consent text for settings:manage (“Change workspace settings”) now reads “Change workspace settings: AI coding, log ingestion and notifications.” (it previously described add-ons, integrations, observability connections and retention).