Name the plugin registry where the enumerations count it

6e98134d40b3 · AtlantisPleb · · parent 150a8db6e051

Name the plugin registry where the enumerations count it

Two enumeration guards went red when the plugin registry landed, both
because the new surface arrived unnamed — which is exactly what those
guards exist to catch, so they did their job.

The registry read its own repository join, restating public and ready
instead of composing the predicate. It is a public listing, so the
right answer was not a sixth stated exception but the same one
`OpenAgents.Forge.Anchor` already uses: compose readable_by/2 with no
user, and reach exactly what an anonymous reader reaches. A private
repository publishing a manifest would have disclosed the repository
the same way a published anchor would. REPOSITORY-001 counts seven
composers now, and says why the last two are anonymous.

The `plugin` API family was published and unclassified, which hides a
family from the export question. It is classified as not-user-data
with its reason: a manifest is a published description of code, not a
record an account authors — what a person did with a plugin is their
thread events, which export whole.

The full suite is green: 4,461 tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GoYpb8FEmdxVErsv7ABCYi
Co-Authored-By
Claude Fable 5 <noreply@anthropic.com>

Deploy story

What this commit did to the running system — joined from the forge receipt chain, the part a commit page elsewhere cannot show.

pushed
by user · WAL seq 355 · 2026-08-25T08:55:34.851204Z

Changed files

  • modified INVARIANTS.md
  • modified lib/openagents/data_rights/export_inventory.ex
  • modified lib/openagents/plugins/forge_source.ex
  • modified test/openagents/repositories/visibility_join_test.exs

Diff

4 files changed, +37 -7

INVARIANTS.md modified +7 -4

@@ -3835,10 +3835,13 @@ model, each named below.

3835 3835
  the anonymous one.
3836 3836
- **Listing composes the predicate.** The modules that compose `readable_by/2`
3837 3837
  are `OpenAgents.Repositories`, `OpenAgents.Issues`, `OpenAgents.Projects`,
3838
  `OpenAgents.Notifications`, `OpenAgents.DataRights.AccountExport`, and
3839
  `OpenAgents.Forge.Anchor` — six, not the four the amendment above named. The
3840
  last is the published WAL anchor (`EXIT-005`), which is anonymous and must
3841
  name exactly the repositories an anonymous reader already reaches.
3838
  `OpenAgents.Notifications`, `OpenAgents.DataRights.AccountExport`,
3839
  `OpenAgents.Forge.Anchor`, and `OpenAgents.Plugins.ForgeSource` — seven, not
3840
  the four the amendment above named. The last two are anonymous surfaces and
3841
  must name exactly the repositories an anonymous reader already reaches: the
3842
  published WAL anchor (`EXIT-005`), and the plugin registry index, where a
3843
  private repository's manifest would disclose the repository the same way a
3844
  published anchor would.
3842 3845
- **The predicate's terms live in one file, plus four stated exceptions.**
3843 3846
  Every site in `lib/` naming a repository's `visibility` or `lifecycle_state`
3844 3847
  against `"public"` or `"ready"` is classified, and the four that decide reach
lib/openagents/data_rights/export_inventory.ex modified +14

@@ -398,6 +398,20 @@ defmodule OpenAgents.DataRights.ExportInventory do

398 398
          "task suites, posted by the bench harness. Aggregate measurement " <>
399 399
          "of the product, carrying no record an account authors."
400 400
    },
401
    %{
402
      family: :plugin,
403
      api?: true,
404
      status: :not_user_data,
405
      mechanism: nil,
406
      proof: nil,
407
      issue: nil,
408
      note:
409
        "The plugin registry index: validated manifests discovered from forge " <>
410
          "repositories, each naming an artifact by digest. A manifest is a " <>
411
          "published description of code, not a record an account authors — " <>
412
          "what a person did with a plugin is their thread events, which " <>
413
          "export whole."
414
    },
401 415
    %{
402 416
      family: :capacity,
403 417
      api?: true,
lib/openagents/plugins/forge_source.ex modified +11 -2

@@ -17,11 +17,20 @@ defmodule OpenAgents.Plugins.ForgeSource do

17 17
18 18
  alias OpenAgents.Plugins.Index
19 19
20
  @doc "Return index entries for every public, ready repository that has a manifest.json on its default branch."
20
  @doc """
21
  Return index entries for every repository an anonymous reader can see that
22
  has a `manifest.json` on its default branch.
23
24
  The population composes `OpenAgents.Repositories.readable_by/2` with no user
25
  rather than restating the join (REPOSITORY-001). The registry is a public
26
  listing, so it must name exactly the repositories an anonymous reader
27
  already reaches — a private repository publishing a plugin manifest here
28
  would contradict TRANSPARENCY-001 the same way a published anchor would.
29
  """
21 30
  @spec entries() :: [Index.Entry.t()]
22 31
  def entries do
23 32
    OpenAgents.Repositories.Repository
24
    |> from(where: [visibility: "public", lifecycle_state: "ready"])
33
    |> OpenAgents.Repositories.readable_by(nil)
25 34
    |> OpenAgents.Repo.all()
26 35
    |> Enum.flat_map(&entries_for_repository/1)
27 36
  end
test/openagents/repositories/visibility_join_test.exs modified +5 -1

@@ -84,7 +84,11 @@ defmodule OpenAgents.Repositories.VisibilityJoinTest do

84 84
      "the pull requests, stacks, and issue dependencies an export may carry",
85 85
    OpenAgents.Forge.Anchor =>
86 86
      "the repositories the published WAL anchor names, which is an anonymous " <>
87
        "surface and must reach exactly what an anonymous reader already reaches"
87
        "surface and must reach exactly what an anonymous reader already reaches",
88
    OpenAgents.Plugins.ForgeSource =>
89
      "the repositories the plugin registry index draws manifests from, which " <>
90
        "is a public listing and must reach exactly what an anonymous reader " <>
91
        "already reaches"
88 92
  }
89 93
90 94
  # Every site in `lib/` that names the predicate's own terms — a repository's

This page updates live while a promote is in flight · changelog