Security-settings baseline
The settings every account that runs SCOPE must have, so a change made in a dashboard can be seen. Draft 29 Oct 2026. Owner: Dan (platform). Approver: Kyle. SOC 2 CC7.1 ("uses defined configuration standards"), CC8.1 ("creates baseline configuration of IT technology"); item TS-13.
How it is used. Once a month, python3 scripts/compliance/baseline_check.py --save reads every
setting below that an API or CLI will give us and writes REQUIRED beside ACTUAL into
evidence/<year>/<date>-security-baseline.md; the person running it reads the "Dashboard" rows by
hand and fills them in the same file (control calendar, monthly). A
DRIFT is either an open readiness item (the row names it) or a change somebody made by hand:
put it back, or change this file through a pull request, and log the change either way in the
dashboard change log of the change-management policy (TS-9).
Changing the baseline is a pull request against this file and the script together, like any other change. The IDs below are never renumbered: the evidence files cite them.
Where it applies. The Lucent Axis accounts only: GitHub org lucent-axis and its repo
scope, Vercel team lucent-axis and its project scope-web, Supabase organization Lucent
Axis and its project scope-dev. Each client's own production and staging project is added
to the script's SUPABASE_PROJECTS (and its Vercel project beside scope-web) the day it is
made (VE-1). The personal demo accounts are outside the audit boundary and are not checked.
What the database itself must hold (RLS on every table, nothing readable signed out, audit
columns, append-only history) is not repeated here. That is checked by the verify_*.sql
scripts in CI's nightly job, against a database, which is stronger than reading a dashboard.
The "29 Oct" column is the first run, saved as docs/compliance/evidence/2026/2026-10-29-security-baseline.md.
Who can change: the account role that holds the switch.
GitHub
| ID | Setting | Required | Why | Checked | Who can change | 29 Oct |
|---|---|---|---|---|---|---|
| GH-1 | Repo lucent-axis/scope visibility |
Private | Source and history stay inside the org (SC-2) | Script | Org Owner | OK |
| GH-2 | Ruleset main on the default branch |
Active, with exactly the rules in .github/rulesets/main.json: no deletion, no force push, pull request required, the five required checks (check, secrets, pre-commit, build, data), no bypass |
Every change to main is a reviewed, tested pull request (SC-5, ORG-07) | Script, rule by rule against the file | Repo admin | OK |
| GH-3 | Dependabot alerts | On | Known vulnerable dependencies are reported (ORG-26, SC-7) | Script | Repo admin | OK |
| GH-4 | Actions GITHUB_TOKEN default |
Read-only, and cannot approve pull requests | A workflow cannot write to the repo or approve its own change unless its file asks | Script | Repo admin | OK |
| GH-5 | Org requires two-factor | On | ORG-06 | Script, when an Owner runs it | Org Owner | Owner only |
| GH-6 | Members may create public repositories | No | A member cannot publish code or data by mistake; only an Owner makes a repo public | Script | Org Owner | DRIFT: yes |
| GH-7 | Org Owners | Two or more | Nobody's absence locks the account (OW-6) | Script | Org Owner | DRIFT: 1 (OW-6) |
| GH-8 | GitHub secret scanning | Off is accepted: it needs Advanced Security on a private repo. Gitleaks runs instead as the required secrets check (GH-2), and the bundle scan in CI (SC-3) |
Free first | Dashboard | Repo admin | Accepted |
Vercel
| ID | Setting | Required | Why | Checked | Who can change | 29 Oct |
|---|---|---|---|---|---|---|
| VC-1 | Team MFA | Enforced | ORG-06, VE-4 | Script | Team Owner | OK |
| VC-2 | scope-web deployment protection |
Vercel Authentication on every deployment except the production custom domain (or stricter); no protection-bypass tokens | A preview cannot be opened by somebody outside the team (VE-3) | Script | Team Owner | OK |
| VC-3 | scope-web function region |
A US region (iad1 today) |
Data is processed in the US (VN-4) | Script | Project member | OK |
| VC-4 | scope-web Git fork protection |
On | A pull request from a fork cannot run a deployment with our variables | Script | Project member | OK |
| VC-5 | Database credentials in scope-web's variables |
None: no SUPABASE_SERVICE_ROLE_KEY, SUPABASE_SECRET_KEY, SUPABASE_JWT_SECRET, SUPABASE_DB_URL or POSTGRES_*. The app runs on the publishable key and RLS. Names only are read, never a value |
A key that bypasses RLS never sits where a build can reach it (VE-2) | Script | Project member | DRIFT: the Supabase integration copied ten in on 27 Oct (VE-2; this-week.md says to delete them once the database password is in the vault) |
| VC-6 | Team sensitive-variable policy | On: a new variable cannot be read back in the dashboard | VE-2 | Script | Team Owner | DRIFT: default |
| VC-7 | Team Owners | Two or more | OW-6 | Script | Team Owner | DRIFT: 1 (OW-6) |
| VC-8 | Log drain | A drain to storage kept 12 months, before any customer data. Until then: Pro keeps runtime logs 1 day | LM-1 | Script | Team Owner | DRIFT: none (LM-1, Kyle's decision) |
Supabase
| ID | Setting | Required | Why | Checked | Who can change | 29 Oct |
|---|---|---|---|---|---|---|
| SB-1 | scope-dev SSL enforcement |
Enforced | No database connection in clear text (DB-7) | Script | Org Owner or Administrator | DRIFT: not enforced (DB-7) |
| SB-2 | scope-dev network restrictions |
Not open to every address: no 0.0.0.0/0 or ::/0 |
Only known addresses reach the database directly (DB-7) | Script | Org Owner or Administrator | DRIFT: open to all (DB-7) |
| SB-3 | scope-dev region |
A us- region (us-east-1 today) |
VN-4 | Script | Fixed at creation | OK |
| SB-4 | scope-dev backups |
Daily backups on, the last within two days. PITR on in every client production project; off is accepted on scope-dev, which holds synthetic data only |
AV-2 | Script | Org Owner | OK |
| SB-5 | Organization requires MFA | On | ID-1, ORG-06 | Dashboard: Organization > Settings > Security | Org Owner | Off (ID-1; both members have MFA on) |
| SB-6 | Organization Owners | Two or more | OW-6 | Dashboard: Organization > Settings > Team | Org Owner | 1 (OW-6) |
| SB-7 | Email sign-in password rules | Minimum 12 characters, letters and digits, leaked-password protection on. The same rules are in supabase/config.toml for local databases |
ID-7 | Dashboard: Project > Authentication > Providers > Email | Org Owner or Administrator | To read (ID-7 open) |
| SB-8 | Log drain | As VC-8. Until then: Pro keeps logs 7 days | LM-1 | Dashboard: Project > Settings > Log Drains | Org Owner | Not yet required (LM-1) |
| SB-9 | Data API exposed schemas | public and graphql_public only; app, sales, demo_baseline and the rest are never exposed |
What the API can reach at all (DB-1, NP-1) | Dashboard: Project > Settings > API | Org Owner or Administrator | To read |
Not in the baseline yet
- Google Workspace (2-Step Verification enforced, who is an admin): added when the Workspace admin is named; read today in the access review (ORG-20).
- AWS (Bedrock's role, root MFA, no access keys on the root): the account does not exist yet (OW-5).
- A compliance platform reads most of these continuously once one is chosen (ORG-04); the script and this file are the free route until then, and stay as the record of what we chose.