Skip to content

Security

Credentials, grants, transport, evidence, and accepted risks for Rackspace schemas

Shared account

Trevor Gerhardt accepted the shared-account risks on 2026-09-07. This page owns the current grant, Preview exposure, and controls.

Local generation, Preview, and Production use one shared MySQL account. The account has this exact global grant profile:

SELECT, INSERT, UPDATE, DELETE, SHOW DATABASES, SHOW VIEW, TRIGGER, EVENT ON *.*

It has no grant option and no other database, table, account-management, or server-administration privilege. A separate USAGE ON *.* grant adds no privileges.

TRIGGER and EVENT can change those object types. This capability is an accepted risk. Local generation, inspection, and verification issue only package-owned SHOW and SELECT statements. There is no generic application SQL reader. Reviewed database-specific seams can issue data changes under ADR 0011.

The shared account is available to all configured Preview and Production server code. QA and Production share the Rackspace host, so Preview code can reach the visible Production databases. RACKSPACE_ENVIRONMENT=qa makes a database binding open the _qa copy of each mi_ database. tredis_global_dynamic has no QA copy, so a QA deployment uses the Production TREDIS accounts. A fresh-administrator check protects the user interface. It cannot prevent deployed Preview code from reading its own environment variables. This exposure is accepted.

The reviewed data-change seams bind mi_property_value and tredis_global_dynamic. Each supplies its complete generated schema to a typed Services repository. Read callbacks expose only selection. Write callbacks expose typed data changes but no raw execution or stored-procedure call path. The MIDOT routes read and change only the projects of the signed-in TREDIS account. Command verification uses isolated test databases on local MySQL. It does not connect to Preview or Production for a write probe. Global Dynamic user results omit credentials. Its optional legacy encryption key stays in redacted server configuration. Unsupported operations fail before storage access; the service adds no route or legacy identity authorization.

Global Dynamic credential operations send the plaintext password and the legacy encryption key to MySQL as bound query parameters, because the legacy AES expression runs in SQL. They travel over the same unencrypted transport as all other query traffic. This exposure is accepted with the transport risk below.

Transport

Rackspace MySQL uses unencrypted transport. The two Vercel Static IPs and the approved operator VPN limit the network paths. A party that can observe those paths can read the credentials and the query traffic. The application rejects any configured transport mode other than the reviewed mode.

Local files

The protected configuration stays outside the repository with mode 0600. Temporary generation directories stay outside the repository with mode 0700. Installation uses a short-lived protected transaction directory beside the package, so that filesystem renames are atomic. The command removes both kinds of temporary directory on every handled exit.

The committed DDL archive intentionally contains database object names, definitions, and stored-program bodies. A generated file or receipt must not contain a connection value, a credential, a raw grant, a local path, a Git identity, a Vercel value, or a raw provider error. Protected-value scanning rejects credentials and known secret forms.

Audit and results

Preview records a safe intent event before it connects and a safe result event afterward. Production stores immutable registry snapshots, saved results, and safe audit events on report rows. Reports exclude failed object names and raw provider errors. The application scans each result before it is saved. Credentials stay inside server actions and never enter browser state or report data. Every server action is private and uses the normal authenticated request boundary.

Verification requests advance sequentially. A failed result stops the run. A restart creates a new report and does not alter an earlier report.

The unsigned generation receipt proves file integrity only. Git review and CI provide author and approval evidence.

Accepted risks

RiskDecision or control
The shared account can read and change data in every visible database.Accepted. Generation, inspection, and verification remain read-only. Reviewed database-specific seams can issue scoped data changes. Credentials stay protected. Write tests use isolated concourse_test_* databases on local MySQL. Each test account has the same global grants, so test code must use only the databases that its fixture created.
TRIGGER and EVENT can change database objects.Accepted. The account has the exact reviewed grants without grant option. Concourse never issues those statements.
Preview server code receives the same global credential as Production.Accepted. Preview exposes only a fixed QA check, requires a fresh administrator, and records audit events.
MySQL transport is unencrypted.Rackspace firewall rules permit only the approved Static IPs and the operator VPN. Every check rejects a different transport mode.
An operator can select the wrong visible database.The chooser has no default and requires an explicit Production confirmation. The complete generated diff and receipt are reviewed in the pull request.
The committed DDL exposes object names and stored-program bodies.Intentional. Protected-value scanning still rejects credentials and known secret forms.
A hard crash can interrupt the worktree installation.Handled errors and signals roll back in process. After a power loss or an uncatchable kill, the operator restores the generated paths with Git.
The unsigned receipt does not prove who ran the generation.Git authorship, branch protection, CI, and human review provide provenance. The receipt proves only the consistency of the committed bytes.
A source schema can change during generation.Two complete passes must produce identical normalized Drizzle output and DDL. Any difference stops the installation.
The history of the former remote-generation design is deleted.Intentional. Old verification rows described browser-selected subsets and had no commit identity. Generic audit events remain. Git keeps the old pages.