Skip to content

Says a chart is keyed by its content hash alone - #86

Merged
johnnyt merged 1 commit into
mainfrom
sp-e8c-chart-key-tenancy-docs
Sep 6, 2026
Merged

Says a chart is keyed by its content hash alone#86
johnnyt merged 1 commit into
mainfrom
sp-e8c-chart-key-tenancy-docs

Conversation

@johnnyt

@johnnyt johnnyt commented Sep 6, 2026

Copy link
Copy Markdown
Member

What

StatifierPersistence.Storage.save_chart/3 keys a chart on
Machine.identity/1's content_hash and nothing else. No tenant,
namespace, or host scope takes part in the key, so two tenants that store
byte-identical charts share one chart row. The moduledoc said where the
hash comes from but never what follows from it, and the question a
multi-tenant host asks first was answered nowhere in the package.

Three paragraphs on Storage's moduledoc now say it:

  1. The keying. The hash is a content address; saving the same one twice
    is :ok and does not duplicate the row (the Adapter.save_chart/2
    contract). The hash answers which chart these bytes are, never who
    stored them.
  2. The tenant consequence. A multi-tenant host tenant-qualifies its own
    per-chart rows, in its own tables. This package stores nothing per
    tenant; a run's opaque metadata map (ADR-0006) is where a host tags a
    run with the scope it already keys its own tables by.
  3. The namespace question is upstream's. Folding a namespace into the
    hash would change what a chart's identity is, which is
    Statifier.Machine.identity/1's question - statifier-ex's contract, not
    this package's. Nothing here proposes it and no option to do it is
    offered.

InMemory's moduledoc mirrors the first two on its chart map, and the
README says it once at the end of "Listing runs by host scope", which is
where a multi-tenant host reads about scope.

Zero code change

Machine-checked, not asserted: stripping every @moduledoc/@doc/
@typedoc heredoc from both modules at this HEAD and at origin/main
leaves the two files byte-identical. The diff is 30 added lines and 0
removed lines across three files, every one of them inside a docstring or
README prose.

No new surface: grep for def register, def positions, :namespace
and namespace: across lib/ returns zero hits, here as on main.

Verification

  • Full mix quality green on this HEAD: format, compile (warnings as
    errors), credo, dialyzer, deps, 482/482 tests, 95.7% coverage. Doctor,
    Gettext and Sobelow are the project's standing not-applicable skips.
  • mix docs renders clean, and each of the three claims was grepped out of
    the generated StatifierPersistence.Storage.html and
    StatifierPersistence.Storage.InMemory.html - the acceptance criteria
    checked against the artefact a host actually reads, not against the
    source.
  • No new tests, so no sabotage notes are due; the gate's sabotage scan
    reports nothing missing and nothing unverifiable.

No changelog fragment

changelog.d/README.md puts documentation on its "do not write a fragment
for" side, and nobody calling the public API can tell the difference: the
behaviour described is the behaviour that already shipped. Consistent with
the sp-a4x and sp-gb2 precedent, neither of which carried one.

Refs: sp-e8c

Closes sp-e8c

Storage.save_chart/3 keys a chart on Machine.identity/1's
content_hash and nothing else - no tenant, namespace, or host scope
takes part in the key - so two tenants storing byte-identical charts
share one chart row. The moduledoc said where the hash comes from
but never what follows from it, and the question a multi-tenant host
asks first went unanswered.

Storage's moduledoc now says all three parts: the keying, the
consequence that a host tenant-qualifies its own per-chart rows in
its own tables, and that folding a namespace into the hash would
change what a chart's identity is - statifier-ex's contract, not
this package's, and not an option offered here. InMemory's moduledoc
mirrors the first two, and the README says it once beside the run
metadata map, which is where a host reads about scope.

Docs only: no fragment, since changelog.d/README.md puts
documentation on its "do not" side, and zero code change - stripping
the docstrings leaves both modules byte-identical to main.

Refs: sp-e8c
@johnnyt
johnnyt merged commit 7790863 into main Sep 6, 2026
1 check passed
@johnnyt
johnnyt deleted the sp-e8c-chart-key-tenancy-docs branch September 6, 2026 23:25
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