Skip to content

Lens Versioning Schema

Tables

lenses.versions

Immutable snapshots of a lens's template body. Published versions cannot be modified.

ColumnTypeNotes
iduuidPK
lens_iduuidFK -> lenses.lenses
version_numberintAuto-incremented per lens
template_bodytextLens template with placeholders. Min 50 chars.
statuscontent_statusdraft -> published -> archived
changelogtextOptional release note
parent_version_iduuidFK -> self (for forked versions)
published_attimestamptzSet automatically on publish
created_attimestamptz

Constraints:

  • lens_versions_template_body_min_length: length(trim(template_body)) >= 50 for ALL statuses.
  • published_at is non-null if and only if status = 'published' (CHECK constraint).

Note: template_body was removed from lenses.lenses in migration 20260324000000. The canonical content now lives exclusively in lenses.versions.

lenses.version_parameters

Typed parameter definitions per version. Parameters belong to versions, not to the lens asset.

ColumnTypeNotes
iduuidPK
version_iduuidFK -> lenses.versions
keytextTemplate placeholder name
typetexttext, number, boolean, select, textarea, json
requiredboolean
default_valuetext
validation_schemajsonbOptional JSON Schema for validation
optionsjsonbFor select type: [{label, value}]

lenses.parameters (DEPRECATED)

Legacy parameter definitions at the lens level. Use lenses.version_parameters instead.

lenses.version_resources

Junction table binding resources to named version slots.

ColumnTypeNotes
version_iduuidFK -> lenses.versions
resource_iduuidFK -> ai.resources
binding_keytextNamed slot: context_doc, reference_image, etc.

Views

lenses.vw_lens_version_history

All versions with parameter count. Use .eq('status', 'published') to filter published-only.

lenses.vw_published_versions

Published versions only, with parameter count.

lenses.vw_lenses

Lenses with latest non-archived version metadata (via LATERAL join), original translation, and author profile. template_body is sourced from the version, not from the lens row.

lenses.vw_fork_history

Recursive fork ancestry chain. Query by lens_id to get all ancestors. Depth 1 = immediate parent. Capped at 20 levels.

RPCs

FunctionSecurityDescription
lenses.fn_lens_create(...)DEFINERAtomic lens creation: lens + version 1 + translation + tags.
lenses.fn_lens_update(...)DEFINERAtomic lens update: visibility, template body (via version upsert), translation, tags.
lenses.fn_upsert_draft_version(p_lens_id, p_template_body, ...)DEFINERCreates/updates draft version. Validates 50-char minimum.
lenses.fn_publish_version(p_version_id)DEFINEROwnership check + atomic draft -> published transition.
lenses.fn_clone_lens(p_source_lens_id, p_version_id)DEFINERClones from published version of public+published lens only.
lenses.fn_list_versions(p_lens_id)INVOKERLists versions descending. Caller RLS applies.

Architecture

Version lifecycle

draft -> published -> archived
  • Draft: Editable. Only one draft per lens at a time. fn_upsert_draft_version reuses existing draft or creates new version.
  • Published: Immutable. published_at is set. Cannot be modified.
  • Archived: Soft-deleted. Excluded from "latest version" resolution in views.

Content ownership

template_body lives exclusively in lenses.versions. The lenses.lenses table stores only metadata (visibility, status, fork lineage). This eliminates the previous dual-write sync via triggers.

Cloning rules

  • Only public + published lenses can be cloned.
  • Only published versions can be selected as clone source.
  • Cloned lens is created as private with parent_lens_id set to source.

Rollback

sql
-- See bottom of supabase/migrations/20260324000000_lens_schema_refactor.sql