Skip to content

feat(meta): add scope block to _meta introspection plugin#1396

Merged
pyramation merged 3 commits into
mainfrom
feat/meta-scope
Jul 18, 2026
Merged

feat(meta): add scope block to _meta introspection plugin#1396
pyramation merged 3 commits into
mainfrom
feat/meta-scope

Conversation

@pyramation

@pyramation pyramation commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a scope block to each table in the graphile _meta query, exposing the constructive-db provisioning scope so codegen can auto-inject scope keys (databaseId/orgId), group generated clients/CLI/docs by tier, and pick the right RLS/JWT context for seeds. Follows the storage/search precedent (smart tag → builder → Meta* GraphQL type).

The @scope smart tag is the sole source of truth — no column-name inference. Key columns are named freely by each generator, so guessing them (entity_id/owner_id/${scope}_id) is brittle. Instead the DB emits everything and the plugin reads it verbatim.

New GraphQL shape on MetaTable:

scope {
  scope        # 'platform' | 'app' | 'database' | entity scope e.g. 'org'
  tier         # 'global' | 'database' | 'entity'
  keyColumn    # inflected key col e.g. 'databaseId'/'orgId', null for global
  entityTable  # SQL name of entity table for entity scopes, else null
  source       # always 'smartTag'
}

Detection (scope-meta-builders.tsbuildScopeMeta):

const tags = codec.extensions?.tags;
if (!tags?.scope) return null;              // no tag → null, never guess
if (!isValidTier(tags.scopeTier)) throw;    // DB must supply the tier
return {
  scope: tags.scope,
  tier: tags.scopeTier,                      // 'global' | 'database' | 'entity'
  keyColumn: tags.scopeKey ? inflect(tags.scopeKey) : null,  // verbatim
  entityTable: tags.scopeEntityTable ?? null,
  source: 'smartTag',
};

Changes

  • types.tsScopeMeta interface + ScopeTier type; scope: ScopeMeta | null on TableMeta; source: 'smartTag'.
  • scope-meta-builders.ts (new) — buildScopeMeta, tag-only, no inference; throws on a @scope tag missing a valid scopeTier.
  • table-meta-builder.ts — wire buildScopeMeta into buildTableMeta.
  • graphql-meta-field.tsMetaScope object type + nullable scope field on MetaTableType.
  • Tests — meta-schema.test.ts covers database/global/entity tags (entity uses a freely-named key tenant_ref read verbatim), null-when-untagged (even with a database_id column present), and the missing-scopeTier throw. Regenerated downstream introspection/SDL snapshots (graphql/test, graphql/server-test).
  • graphile-meta skill — documents the "DB emits all fields; plugin reads verbatim; never guess columns" contract.

Follow-up (separate constructive-db PR)

Emit the tag from apply_scope_fields.sql:

PERFORM metaschema.append_table_smart_tags(
  v_table_id,
  jsonb_build_object('scope', v_scope, 'scopeTier', v_tier,
                     'scopeKey', v_key_col, 'scopeEntityTable', v_entity_table)
);

Until that lands, _meta.scope is null for all tables (the tag isn't emitted yet) — which is the correct, non-brittle default.

Link to Devin session: https://app.devin.ai/sessions/819d1e4face6493393be40f35a48af33
Requested by: @pyramation

Surfaces provisioning scope per table in _meta: scope, tier
(global/database/entity), keyColumn, entityTable, and source
(smartTag|inferred). Reads the @scope smart tag with a database_id
column-inference fallback. Includes unit tests + updated snapshots.
@pyramation pyramation self-assigned this Jul 18, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@blacksmith-sh

This comment has been minimized.

Remove all column-name inference from buildScopeMeta. scope, tier,
keyColumn (verbatim), and entityTable now come only from the @scope
smart tag (scope/scopeTier/scopeKey/scopeEntityTable); untagged tables
return null. Throws if the tag is present without a valid scopeTier.
@pyramation
pyramation merged commit 6397e12 into main Jul 18, 2026
38 checks passed
@pyramation
pyramation deleted the feat/meta-scope branch July 18, 2026 11:20
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.

1 participant