Skip to content

feat(storage): tenant-safe config read + bucket type/isPublic provisioning#1311

Open
yyyyaaa wants to merge 1 commit into
mainfrom
feat/storage-uploads-e2e
Open

feat(storage): tenant-safe config read + bucket type/isPublic provisioning#1311
yyyyaaa wants to merge 1 commit into
mainfrom
feat/storage-uploads-e2e

Conversation

@yyyyaaa

@yyyyaaa yyyyaaa commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

What

The graphile-plugin half of the storage-uploads work. Pairs with constructive-db PR (resolve_storage_modules accessor) and dashboard PR #235 (client seam + provisioning preset).

graphile-presigned-url-plugin — RLS-safe storage config read. storage-module-cache.ts now reads a tenant's storage config through metaschema_modules_public.resolve_storage_modules($database_id) (the SECURITY DEFINER accessor) instead of a direct SELECT … FROM storage_module, which RLS blocks for a tenant role (returns 0 rows). Without this, the presigned mutation can't resolve the bucket/config for the calling database.

graphile-bucket-provisioner-plugintype / isPublic on provision. provisionBucket accepts type and isPublic; when the bucket row doesn't yet exist it ensures the row + S3 bucket with a consistent access type (ensureType = requestedType || (isPublic ? 'public' : 'private')), ON CONFLICT no-op if it does. Reuses @constructive-io/bucket-provisioner for the actual S3 ops (no reimplementation).

Why

Provisioned tenant databases expose storage on the data API (see the constructive-db + dashboard PRs), but the presigned plugin couldn't read the per-tenant storage config under RLS, and bucket provisioning didn't carry the public/private intent. These two changes close that.

Validation

Deployed to the hub backend and verified end-to-end: a freshly provisioned database uploaded a file from the dashboard data grid → the presigned plugin resolved storage config via resolve_storage_modules → presigned PUT to MinIO returned 200app_files row + user-table reference persisted. (CI builds the plugins; the worktree itself isn't installed locally.)

Notes

plugin.test.ts uses jest globals (the package's configured runner) — editor "cannot find name jest" warnings are pre-existing type-resolution noise, not introduced here.

…oning

graphile-presigned-url-plugin reads storage config via the resolve_storage_modules
SECURITY DEFINER accessor. The direct storage_module select returns 0 rows under
tenant RLS, so this is required for the presigned mutation to resolve bucket/file
table names on every upload. graphile-bucket-provisioner-plugin's provisionBucket
gains type/isPublic and ensures the bucket row + S3 access type stay consistent;
reuses @constructive-io/bucket-provisioner for S3 ops.
@yyyyaaa yyyyaaa requested a review from pyramation June 26, 2026 03:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants