Skip to content

Commit 4c56615

Browse files
authored
Merge pull request #1039 from constructive-io/feat/consolidate-storage-provisions
feat: rename storage_table_provisions → provisions, remove storage_config.policies type
2 parents 018de0b + 8543353 commit 4c56615

2 files changed

Lines changed: 8 additions & 75 deletions

File tree

graphql/node-type-registry/src/blueprint-types.generated.ts

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -831,19 +831,6 @@ export interface BlueprintTableUniqueConstraint {
831831
/** Optional schema name override. */
832832
schema_name?: string;
833833
}
834-
/** A storage-specific RLS policy object for apply_storage_security(). Each entry defines an Authz* policy with explicit privileges, scoped to specific storage tables. */
835-
export interface BlueprintStoragePolicy {
836-
/** Authz* policy generator type (e.g., "AuthzPublishable", "AuthzDirectOwner", "AuthzEntityMembership"). */
837-
$type: string;
838-
/** Privilege array (e.g., ["select", "insert", "update", "delete"]). Intersected with each storage table's supported operations. */
839-
privileges: string[];
840-
/** Policy data config. Auto-derived from $type when omitted (e.g., AuthzPublishable defaults to {"is_published_field": "is_public", "require_published_at": false}). */
841-
data?: Record<string, unknown>;
842-
/** Which storage tables to apply this policy to. Defaults to all three when omitted. Uses logical names (not prefixed). */
843-
tables?: ('buckets' | 'files' | 'upload_requests')[];
844-
/** Custom RLS policy name suffix. Auto-derived from $type when omitted (pub/own/mem). */
845-
policy_name?: string;
846-
}
847834
/** A bucket seed entry for storage_config.buckets[]. Creates an initial bucket row in the {prefix}_buckets table during entity type provisioning. Only used for app-level storage (not entity-scoped). */
848835
export interface BlueprintBucketSeed {
849836
/** Bucket key name (e.g., "avatars", "documents"). Becomes the key column value. */
@@ -859,10 +846,8 @@ export interface BlueprintBucketSeed {
859846
/** CORS allowed origins for this bucket. */
860847
allowed_origins?: string[];
861848
}
862-
/** Storage configuration for an entity type. Controls RLS policies on storage tables, seeds initial buckets, and overrides module-level settings (expiry times, file size limits, CORS). */
849+
/** Storage configuration for an entity type. Seeds initial buckets, overrides module-level settings (expiry times, file size limits, CORS), and provides per-table provisioning overrides via provisions. */
863850
export interface BlueprintStorageConfig {
864-
/** Custom RLS policies for storage tables. When provided, replaces the default policy set (AuthzPublishable + membership + AuthzDirectOwner). Each entry is a policy object with $type, privileges, and optional data/tables/policy_name. */
865-
policies?: BlueprintStoragePolicy[];
866851
/** Initial bucket seed entries. Each creates a row in {prefix}_buckets during provisioning. Only used for app-level storage (not entity-scoped). */
867852
buckets?: BlueprintBucketSeed[];
868853
/** Override for presigned upload URL expiry time in seconds. */
@@ -873,8 +858,8 @@ export interface BlueprintStorageConfig {
873858
default_max_file_size?: number;
874859
/** CORS allowed origins for the storage module. */
875860
allowed_origins?: string[];
876-
/** Per-table overrides for storage tables. Each key targets a specific storage table (files, buckets, upload_requests) and uses the same shape as table_provision: { nodes, fields, grants, use_rls, policies }. Fanned out to secure_table_provision targeting the corresponding table. */
877-
storage_table_provisions?: {
861+
/** Per-table overrides for storage tables. Each key targets a specific storage table (files, buckets, upload_requests) and uses the same shape as table_provision: { nodes, fields, grants, use_rls, policies }. Fanned out to secure_table_provision targeting the corresponding table. When a key includes policies[], those REPLACE the default storage policies for that table; tables without a key still get defaults. */
862+
provisions?: {
878863
files?: BlueprintEntityTableProvision;
879864
buckets?: BlueprintEntityTableProvision;
880865
upload_requests?: BlueprintEntityTableProvision;
@@ -1160,6 +1145,6 @@ export interface BlueprintDefinition {
11601145
unique_constraints?: BlueprintUniqueConstraint[];
11611146
/** Entity types to provision in Phase 0 (before tables). Each entry creates an entity table with membership modules and security. */
11621147
entity_types?: BlueprintEntityType[];
1163-
/** App-level storage configuration. Creates a storage_module (membership_type = NULL) with the specified policies, seeds initial buckets, and overrides module-level settings (expiry times, file size limits, CORS). For entity-scoped storage, use entity_types[].has_storage + entity_types[].storage instead. */
1148+
/** App-level storage configuration. Creates a storage_module (membership_type = NULL), seeds initial buckets, and overrides module-level settings (expiry times, file size limits, CORS). Use provisions for per-table policy overrides. For entity-scoped storage, use entity_types[].has_storage + entity_types[].storage instead. */
11641149
storage?: BlueprintStorageConfig;
11651150
}

graphql/node-type-registry/src/codegen/generate-types.ts

Lines changed: 4 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -620,48 +620,6 @@ function buildBlueprintTableUniqueConstraint(): t.ExportNamedDeclaration {
620620
);
621621
}
622622

623-
/**
624-
* Build the BlueprintStoragePolicy interface.
625-
*
626-
* Matches the jsonb policy objects accepted by apply_storage_security():
627-
* { "$type": "AuthzPublishable", "privileges": ["select"], "data": {...}, "tables": [...], "policy_name": "pub" }
628-
*/
629-
function buildBlueprintStoragePolicy(): t.ExportNamedDeclaration {
630-
return addJSDoc(
631-
exportInterface('BlueprintStoragePolicy', [
632-
addJSDoc(
633-
requiredProp('$type', t.tsStringKeyword()),
634-
'Authz* policy generator type (e.g., "AuthzPublishable", "AuthzDirectOwner", "AuthzEntityMembership").'
635-
),
636-
addJSDoc(
637-
requiredProp('privileges', t.tsArrayType(t.tsStringKeyword())),
638-
'Privilege array (e.g., ["select", "insert", "update", "delete"]). Intersected with each storage table\'s supported operations.'
639-
),
640-
addJSDoc(
641-
optionalProp(
642-
'data',
643-
recordType(t.tsStringKeyword(), t.tsUnknownKeyword())
644-
),
645-
'Policy data config. Auto-derived from $type when omitted (e.g., AuthzPublishable defaults to {"is_published_field": "is_public", "require_published_at": false}).'
646-
),
647-
addJSDoc(
648-
optionalProp(
649-
'tables',
650-
t.tsArrayType(
651-
strUnion(['buckets', 'files', 'upload_requests'])
652-
)
653-
),
654-
'Which storage tables to apply this policy to. Defaults to all three when omitted. Uses logical names (not prefixed).'
655-
),
656-
addJSDoc(
657-
optionalProp('policy_name', t.tsStringKeyword()),
658-
'Custom RLS policy name suffix. Auto-derived from $type when omitted (pub/own/mem).'
659-
)
660-
]),
661-
'A storage-specific RLS policy object for apply_storage_security(). Each entry defines an Authz* policy with explicit privileges, scoped to specific storage tables.'
662-
);
663-
}
664-
665623
/**
666624
* Build the BlueprintBucketSeed interface.
667625
*
@@ -713,15 +671,6 @@ function buildBlueprintBucketSeed(): t.ExportNamedDeclaration {
713671
function buildBlueprintStorageConfig(): t.ExportNamedDeclaration {
714672
return addJSDoc(
715673
exportInterface('BlueprintStorageConfig', [
716-
addJSDoc(
717-
optionalProp(
718-
'policies',
719-
t.tsArrayType(
720-
t.tsTypeReference(t.identifier('BlueprintStoragePolicy'))
721-
)
722-
),
723-
'Custom RLS policies for storage tables. When provided, replaces the default policy set (AuthzPublishable + membership + AuthzDirectOwner). Each entry is a policy object with $type, privileges, and optional data/tables/policy_name.'
724-
),
725674
addJSDoc(
726675
optionalProp(
727676
'buckets',
@@ -752,7 +701,7 @@ function buildBlueprintStorageConfig(): t.ExportNamedDeclaration {
752701
),
753702
addJSDoc(
754703
optionalProp(
755-
'storage_table_provisions',
704+
'provisions',
756705
t.tsTypeLiteral([
757706
optionalProp(
758707
'files',
@@ -768,10 +717,10 @@ function buildBlueprintStorageConfig(): t.ExportNamedDeclaration {
768717
)
769718
])
770719
),
771-
'Per-table overrides for storage tables. Each key targets a specific storage table (files, buckets, upload_requests) and uses the same shape as table_provision: { nodes, fields, grants, use_rls, policies }. Fanned out to secure_table_provision targeting the corresponding table.'
720+
'Per-table overrides for storage tables. Each key targets a specific storage table (files, buckets, upload_requests) and uses the same shape as table_provision: { nodes, fields, grants, use_rls, policies }. Fanned out to secure_table_provision targeting the corresponding table. When a key includes policies[], those REPLACE the default storage policies for that table; tables without a key still get defaults.'
772721
)
773722
]),
774-
'Storage configuration for an entity type. Controls RLS policies on storage tables, seeds initial buckets, and overrides module-level settings (expiry times, file size limits, CORS).'
723+
'Storage configuration for an entity type. Seeds initial buckets, overrides module-level settings (expiry times, file size limits, CORS), and provides per-table provisioning overrides via provisions.'
775724
);
776725
}
777726

@@ -1020,7 +969,7 @@ function buildBlueprintDefinition(): t.ExportNamedDeclaration {
1020969
'storage',
1021970
t.tsTypeReference(t.identifier('BlueprintStorageConfig'))
1022971
),
1023-
'App-level storage configuration. Creates a storage_module (membership_type = NULL) with the specified policies, seeds initial buckets, and overrides module-level settings (expiry times, file size limits, CORS). For entity-scoped storage, use entity_types[].has_storage + entity_types[].storage instead.'
972+
'App-level storage configuration. Creates a storage_module (membership_type = NULL), seeds initial buckets, and overrides module-level settings (expiry times, file size limits, CORS). Use provisions for per-table policy overrides. For entity-scoped storage, use entity_types[].has_storage + entity_types[].storage instead.'
1024973
)
1025974
]),
1026975
'The complete blueprint definition -- the JSONB shape accepted by construct_blueprint().'
@@ -1093,7 +1042,6 @@ function buildProgram(meta?: MetaTableInfo[]): string {
10931042
statements.push(buildBlueprintTableIndex());
10941043
statements.push(buildBlueprintUniqueConstraint());
10951044
statements.push(buildBlueprintTableUniqueConstraint());
1096-
statements.push(buildBlueprintStoragePolicy());
10971045
statements.push(buildBlueprintBucketSeed());
10981046
statements.push(buildBlueprintStorageConfig());
10991047
statements.push(buildBlueprintEntityTableProvision());

0 commit comments

Comments
 (0)