WSL DB Permission Errors: Cross-Service Grant Investigation
Table of Contents
Overview
On 2026-05-11, setting up OreStudio on a fresh Debian WSL machine revealed permission errors that had not been observed during equivalent provisioning runs on a regular Debian Linux machine using the same code (2-3 days prior). Two missing cross-service DB grants were identified and fixed. A third, deeper issue remains unresolved: why the regular Linux machine was not affected.
Errors Observed
Two distinct permission denied errors appeared in service logs on the
fresh WSL DB:
[ERROR] [ores.variability.repository.system_settings_repository] Query execution failed: ERROR: permission denied for table ores_variability_system_settings_tbl [ERROR] [ores.iam.messaging.bootstrap_handler] ores.dev.local1.iam.v1.bootstrap.status failed: Repository error: ... permission denied for table ores_variability_system_settings_tbl
[ERROR] [ores.refdata.repository.party_repository] Query failed: ERROR: permission denied for table ores_refdata_parties_tbl [ERROR] [ores.iam.repository.account_party_repository] Executing INSERT failed: ERROR: permission denied for table ores_refdata_parties_tbl [ERROR] [ores.iam.messaging.bootstrap_handler] ores.dev.local1.iam.v1.bootstrap.provision-tenant failed: ... permission denied for table ores_refdata_parties_tbl
And separately:
[ERROR] [ores.compute.service] permission denied for table ores_dq_change_reasons_tbl
Root Cause
All three errors share the same structural cause: the service registry model
(projects/ores.codegen/models/services/ores_services_service_registry.json)
was missing cross-service SELECT/DML grants that were needed by:
| Service | Table | Access needed |
|---|---|---|
iam |
ores_variability_system_settings_tbl |
SELECT |
iam |
ores_refdata_parties_tbl |
DML |
compute |
ores_dq_change_reasons_tbl |
SELECT |
The generated file projects/ores.sql/create/iam/iam_service_db_grants_create.sql
is produced from the model via the service-registry codegen profile. Because
the grants were absent from the model since the least-privilege commit
(532dc2bd6, 2026-03-28), a fresh recreate_database.sh run produced a
database missing these grants.
Why the variability grant was missing
The IAM service directly links ores.variability.core and calls
variability::service::system_settings_service to read system flags
(system.user_signups, system.signup_requires_authorization, etc.) on
startup and during login. This is a direct DB connection as the
iam_service user — no NATS hop. The grant was simply never added to the
model.
Why the parties grants were missing
projects/ores.iam.core/include/ores.iam.core/messaging/bootstrap_handler.hpp
(line 203) instantiates refdata::repository::party_repository and
service::account_party_service directly as the IAM service user after
calling ores_iam_provision_tenant_fn. The SECURITY DEFINER function
handles the tenant INSERT as the DDL user, but the subsequent C++ repository
calls run as iam_service_user and need explicit grants on
ores_refdata_parties_tbl. These grants were not in the model.
Why the compute grant was missing
The compute service reads ores_dq_change_reasons_tbl (for change-reason
validation) but this cross-service SELECT was not recorded in the model.
Fix Applied
The service registry model was updated and the grants file regenerated:
// iam service entry — before:
"select_tables": []
// iam service entry — after:
"select_tables": [
{"table": "ores_variability_system_settings_tbl"}
],
"dml_prefixes": [
{"prefix": "ores_iam_"},
{"prefix": "ores_refdata_parties"}
]
// compute service entry — added:
{"table": "ores_dq_change_reasons_tbl"}
Commits:
c6e6d5aad— [sql] Grant IAM service SELECT on variability system settings table79e2db2e3— [sql] Fix missing cross-service DB grants for IAM and compute services
Grants were also applied directly to the live WSL database without a full recreate.
The Unresolved Question
The grants have been missing since 532dc2bd6 (2026-03-28). The other
(regular Linux) machine was running the same code 2-3 days before this
investigation and successfully completing the full provisioning wizard flow.
This is inconsistent with the missing grants.
What was ruled out
- The grants were absent in every committed version of the file, confirmed
via
git logthrough all 8 commits touching the file. - The
recreate_database.shscript runs cleanly on WSL with no errors or silent failures — confirmed by capturing the full output. - The
ores_iam_provision_tenant_fnisSECURITY DEFINERand runs as the DDL user — so the SQL-function path for tenant INSERT works regardless. But the C++account_party_repositorycalls that follow do not go through this function and require explicit grants. - The code in
bootstrap_handler.hppcallingparty_repositorydirectly pre-dates the least-privilege commit by over six weeks.
Remaining hypotheses
The most plausible outstanding explanation is a difference in PostgreSQL connection method between the two machines:
- On regular Debian Linux, services may connect via Unix socket. PostgreSQL
pg_hba.confon Debian defaults topeerauthentication for local socket connections. Depending on the OS user running the service, this may resolve to a user with broader privileges. - On WSL, services connect via TCP to
localhost:5432. TCP connections usescram-sha-256and enforce table-level grants strictly.
To confirm: compare pg_hba.conf on both machines and check whether the
service processes on regular Linux connect via socket or TCP.
Related Issues Found During Investigation
populate files diverge from the service registry model
projects/ores.sql/populate/iam/iam_service_accounts_populate.sql and
iam_service_account_roles_populate.sql contain entries for http_user,
wt_user, and compute_wrapper_user that are NOT in the service registry
model. These users are infrastructure users created in
recreate_database.sql directly, outside the codegen flow. Because they
are absent from the model, every codegen regeneration silently removes their
IAM account and role-assignment entries from the generated populate files.
These entries must be either:
- Moved to a static (non-generated) SQL file not managed by codegen, or
- Restored in the model with appropriate metadata to distinguish them from domain services.
Until fixed, any full codegen regeneration followed by a recreate_database.sh
run on a fresh machine will produce a DB where http_user, wt_user, and
compute_wrapper_user have no IAM accounts or role assignments.
Cross-service direct DB access is architectural debt
The IAM service directly queries ores_variability_system_settings_tbl
(by linking ores.variability.core) and ores_refdata_parties_tbl (via
refdata::repository::party_repository). The architectural intent was that
services should not access other services' tables directly; all cross-domain
reads should go via NATS. These direct accesses are technical debt that
should be refactored to use NATS-based service calls.