Liking cljdoc? Tell your friends :D

eacl.migrations.v6-to-v7

One-time migration from EACL v6 relationship storage to the v7 tuple model.

v6 stored one Datomic entity per relationship (7 datoms across :eacl.relationship/* attributes). v7 stores each relationship as two cardinality-many tuple datoms asserted directly on your domain entities:

[:db/add <subject-eid> :eacl.v7.relationship/subject-type+relation+resource-type+resource [<subject-type> <relation-eid> <resource-type> <resource-eid>]] [:db/add <resource-eid> :eacl.v7.relationship/resource-type+relation+subject-type+subject [<resource-type> <relation-eid> <subject-type> <subject-eid>]]

where <relation-eid> refers to the Relation schema entity, not the relation name keyword.

Entry points:

  • migrate! runs the whole migration end-to-end (see its docstring for the exact steps). It is idempotent and converges storage forward: verified v7 tuples replace the v6 relationship entities in the same run.
  • assert-storage-compatible! is a read-only legacy-source diagnostic. Ordinary clients require the subsequent storage 7-to-8 migration.

Flat v6 permissions are converted once to canonical expression entities. Pass your SpiceDB schema string as {:schema ...} to validate and replace the stored schema from source. Without it, migrate! deterministically converts the stored union-only rows. normalize-schema-entity-ids! first gives legacy schema entities the canonical :eacl/id handles the replacement needs.

Full walkthrough and edge cases: docs/migration-v6-to-v7.md.

One-time migration from EACL v6 relationship storage to the v7 tuple model.

v6 stored one Datomic entity per relationship (7 datoms across
:eacl.relationship/* attributes). v7 stores each relationship as two
cardinality-many tuple datoms asserted directly on your domain entities:

  [:db/add <subject-eid>  :eacl.v7.relationship/subject-type+relation+resource-type+resource
   [<subject-type> <relation-eid> <resource-type> <resource-eid>]]
  [:db/add <resource-eid> :eacl.v7.relationship/resource-type+relation+subject-type+subject
   [<resource-type> <relation-eid> <subject-type> <subject-eid>]]

where <relation-eid> refers to the Relation schema entity, not the relation
name keyword.

Entry points:
- `migrate!` runs the whole migration end-to-end (see its docstring for the
  exact steps). It is idempotent and converges storage forward: verified v7
  tuples replace the v6 relationship entities in the same run.
- `assert-storage-compatible!` is a read-only legacy-source diagnostic.
  Ordinary clients require the subsequent storage 7-to-8 migration.


Flat v6 permissions are converted once to canonical expression entities.
Pass your SpiceDB schema string as {:schema ...} to validate and replace the
stored schema from source. Without it, migrate! deterministically converts
the stored union-only rows. `normalize-schema-entity-ids!` first gives
legacy schema entities the canonical :eacl/id handles the replacement needs.

Full walkthrough and edge cases:
docs/migration-v6-to-v7.md.
raw docstring

assert-storage-compatible!clj

(assert-storage-compatible! conn options)

Read-only legacy storage-7 diagnostic, retained for prerequisite tooling. Current clients use eacl.datomic.storage/assert-compatible! instead.

Read-only legacy storage-7 diagnostic, retained for prerequisite tooling.
Current clients use eacl.datomic.storage/assert-compatible! instead.
raw docstring

backfill-relationship-tuples!clj

(backfill-relationship-tuples! conn {:keys [batch-size] :or {batch-size 500}})

Asserts the v7 tuple pair for every v6 relationship entity, in batches. Additive and idempotent: v6 entities are untouched and re-asserting an existing tuple datom is a no-op. Pause relationship writes while this runs — a v6-side delete racing the backfill would leave a resurrecting tuple. Returns the number of v6 relationships processed.

Asserts the v7 tuple pair for every v6 relationship entity, in batches.
Additive and idempotent: v6 entities are untouched and re-asserting an
existing tuple datom is a no-op. Pause relationship writes while this runs —
a v6-side delete racing the backfill would leave a resurrecting tuple.
Returns the number of v6 relationships processed.
raw docstring

detect-storage-versionclj

(detect-storage-version db)

Classifies the relationship data at rest: :v7 — only v7 tuples (or a stamped migration) :v6 — only v6 relationship entities :mixed — both, i.e. mid-migration or migrated but not yet cleaned up :none — no relationship data at all (fresh database)

Classifies the relationship data at rest:
:v7    — only v7 tuples (or a stamped migration)
:v6    — only v6 relationship entities
:mixed — both, i.e. mid-migration or migrated but not yet cleaned up
:none  — no relationship data at all (fresh database)
raw docstring

ensure-v7-attributes!clj

(ensure-v7-attributes! conn)

Installs the v7 schema attributes. Additive and idempotent against a v6 database: shared attribute definitions are unchanged and only the new attributes (:eacl/schema-version, :eacl/storage-version and the two :eacl.v7.relationship/* tuples) are added.

Installs the v7 schema attributes. Additive and idempotent against a v6
database: shared attribute definitions are unchanged and only the new
attributes (:eacl/schema-version, :eacl/storage-version and the two
:eacl.v7.relationship/* tuples) are added.
raw docstring

migrate!clj

(migrate! conn)
(migrate! conn {:keys [schema batch-size] :or {batch-size 500} :as opts})

End-to-end v6 -> v7 migration. Steps, in order:

  1. ensure-v7-attributes! — install v7 schema attributes (additive)
  2. normalize-schema-entity-ids! — give legacy schema entities :eacl/id handles
  3. migrate-v6-schema! — replace flat permissions with expressions
  4. backfill-relationship-tuples! — v7 tuples for every v6 relationship
  5. verify-backfill — throws unless every v6 row has its tuples
  6. retract-v6-relationship-entities! — remove the superseded v6 entities
  7. stamp-storage-version! — unblocks make-client's startup check

Options:

  • :schema (string, recommended) — your SpiceDB schema DSL string, parsed and validated before it atomically replaces the flat permission rows with canonical expression entities. Relations that are unchanged keep their eids. Without :schema, the stored v6 union-only permission rows are converted deterministically to equivalent expression entities. Note: if the schema string drops a relation that stored v6 relationships still use, step 4 throws :eacl.migration/missing-relation and the migration aborts additively — nothing is lost, fix the schema and re-run.
  • :batch-size (default 500) — relationships per transaction (2 datoms each).

Idempotent: safe to re-run after interruption or as a catch-up pass. Pause relationship writes while it runs. Returns a report map; throws {:type :eacl.migration/incomplete} if verification fails.

End-to-end v6 -> v7 migration. Steps, in order:

1. ensure-v7-attributes!            — install v7 schema attributes (additive)
2. normalize-schema-entity-ids!     — give legacy schema entities :eacl/id handles
3. migrate-v6-schema!               — replace flat permissions with expressions
4. backfill-relationship-tuples!    — v7 tuples for every v6 relationship
5. verify-backfill                  — throws unless every v6 row has its tuples
6. retract-v6-relationship-entities! — remove the superseded v6 entities
7. stamp-storage-version!           — unblocks make-client's startup check

Options:
- :schema (string, recommended) — your SpiceDB schema DSL string, parsed and
  validated before it atomically replaces the flat permission rows with
  canonical expression entities. Relations that are unchanged keep their
  eids. Without :schema, the stored v6 union-only permission rows are
  converted deterministically to equivalent expression entities.
  Note: if the schema string drops a relation that stored v6 relationships
  still use, step 4 throws :eacl.migration/missing-relation and the
  migration aborts additively — nothing is lost, fix the schema and re-run.
- :batch-size (default 500) — relationships per transaction (2 datoms each).

Idempotent: safe to re-run after interruption or as a catch-up pass. Pause
relationship writes while it runs. Returns a report map; throws
{:type :eacl.migration/incomplete} if verification fails.
raw docstring

missing-tuplesclj

(missing-tuples db)

Lazy seq of v6 relationship rows whose v7 forward or reverse tuple is absent (or whose Relation cannot be resolved). Empty after a complete backfill. Streams via per-row index lookups, so it is safe on large databases.

Lazy seq of v6 relationship rows whose v7 forward or reverse tuple is
absent (or whose Relation cannot be resolved). Empty after a complete
backfill. Streams via per-row index lookups, so it is safe on large
databases.
raw docstring

normalize-schema-entity-ids!clj

(normalize-schema-entity-ids! conn)

Asserts the canonical :eacl/id onto any Relation/Permission schema entity missing one (installs that predate the :eacl/id convention). write-schema! addresses schema entities by [:eacl/id ...] when computing retractions, so entities without one cannot be managed — or cleaned up — until normalized.

For pre-unified-permission entities the derived id may contain empty segments; that is fine — it only needs to be a unique handle that lets write-schema! retract the outdated entity. Returns the number of entities normalized (0 on databases written by any recent v6).

Asserts the canonical :eacl/id onto any Relation/Permission schema entity
missing one (installs that predate the :eacl/id convention). write-schema!
addresses schema entities by [:eacl/id ...] when computing retractions, so
entities without one cannot be managed — or cleaned up — until normalized.

For pre-unified-permission entities the derived id may contain empty
segments; that is fine — it only needs to be a unique handle that lets
write-schema! retract the outdated entity. Returns the number of entities
normalized (0 on databases written by any recent v6).
raw docstring

relation-eid-indexclj

(relation-eid-index db)

Maps [resource-type relation-name subject-type] -> Relation schema entity eid. v7 tuples reference Relations by eid, so every migrated relationship must resolve its triple through this index.

Maps [resource-type relation-name subject-type] -> Relation schema entity
eid. v7 tuples reference Relations by eid, so every migrated relationship
must resolve its triple through this index.
raw docstring

retract-v6-relationship-entities!clj

(retract-v6-relationship-entities! conn
                                   {:keys [batch-size] :or {batch-size 500}})

Retracts all v6 relationship entities in batches. Idempotent. Returns the number of entities retracted.

Retracts all v6 relationship entities in batches. Idempotent. Returns the
number of entities retracted.
raw docstring

stamped-storage-versionclj

(stamped-storage-version db)

The :eacl/storage-version long stamped by a completed migrate!, or nil. Fresh installs need no stamp because they contain no v6 relationship data.

The :eacl/storage-version long stamped by a completed migrate!, or nil.
Fresh installs need no stamp because they contain no v6 relationship data.
raw docstring

storage-versionclj

The relationship storage model version this version of EACL reads & writes.

The relationship storage model version this version of EACL reads & writes.
raw docstring

v6-relation-name-attrclj

Every v6 relationship entity carries this attribute exactly once, so its datoms enumerate v6 relationships.

Every v6 relationship entity carries this attribute exactly once, so its
datoms enumerate v6 relationships.
raw docstring

v6-relationship->v7-txesclj

(v6-relationship->v7-txes db relation-index v6-rel-eid)

The two v7 tuple assertions for one v6 relationship entity. Throws {:type :eacl.migration/missing-relation} if the relationship references a [resource-type relation-name subject-type] triple with no Relation schema entity — such rows never granted anything in v6 either; add the Relation to your schema or retract the dead row, then re-run.

The two v7 tuple assertions for one v6 relationship entity. Throws
{:type :eacl.migration/missing-relation} if the relationship references a
[resource-type relation-name subject-type] triple with no Relation schema
entity — such rows never granted anything in v6 either; add the Relation to
your schema or retract the dead row, then re-run.
raw docstring

v6-relationship-eidsclj

(v6-relationship-eids db)

Lazy seq of all v6 relationship entity ids.

Lazy seq of all v6 relationship entity ids.
raw docstring

v6-relationship-schemaclj

The v6 relationship-entity attribute definitions, kept for reference and for test fixtures that need to construct a v6-model database. Nothing in v7 installs or reads these. Datomic cannot uninstall attributes, so migrated databases retain these definitions (inert) forever.

The v6 relationship-entity attribute definitions, kept for reference and for
test fixtures that need to construct a v6-model database. Nothing in v7
installs or reads these. Datomic cannot uninstall attributes, so migrated
databases retain these definitions (inert) forever.
raw docstring

verify-backfillclj

(verify-backfill db)

Reports on backfill completeness. :complete? is true when every v6 relationship has both v7 tuples. v7 counts exceeding the v6 count is not a failure — relationships written through v7 code after deploy have no v6 counterpart.

Reports on backfill completeness. :complete? is true when every v6
relationship has both v7 tuples. v7 counts exceeding the v6 count is not a
failure — relationships written through v7 code after deploy have no v6
counterpart.
raw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close