Clarify create/download/update/publish decision table for shared indexes

Spell out explicitly, per run: check whether the shared index store
already has a published index; if so, fetch it regardless of access
level; a write-access user always continues to rebuild and publish
back to that same store, and this is precisely what creates it there
the first time the store is empty. A read-only user never rebuilds or
publishes anything, whether or not the store already had content.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Michał Kopeć 2026-07-20 16:22:55 +02:00
parent 946619de89
commit dc9f990bdd

View file

@ -27,9 +27,11 @@ Two refinements on top of that base design:
- **Shared, pre-built indexes.** `source.yaml` can declare *where the
already-built index lives* (a git repo, or a shared resource such as a
network path or another connector-reachable location), so a user doesn't
have to build the index from scratch — they just fetch what's already
there.
network path or another connector-reachable location). Every run checks
that location: if it already has an index, fetch it; if it doesn't yet,
a write-access user's run is what creates it there for the first time.
Either way, a read-only user just gets whatever's already there — they
never have to build the index from scratch themselves.
- **Read vs. write access, per user, per source.** Building/refreshing an
index from the live connector is gated by a **local, per-user** setting
(`libs/<name>/source.local.yaml`, never committed) — read-only by
@ -118,32 +120,47 @@ this user is an admin for this one source; anything else (the field is
**per connector-backed lib** — a user can be write-access for one source
and read-only for another.
### Step 3 — Fetch a published index, if one is configured
### Step 3 — Check the shared index store, and fetch it if it exists
If `source.yaml` has an `index:` block, fetch/pull the latest published
index from `index.location` (per `index.store`: `git pull`/clone for
`git`, a plain file copy for a filesystem/network `shared` path, or the
matching connector tool for a `shared` location that needs one) and use it
to refresh `libs/<name>/{index.md,entities/,graph/,log.md}`. Do this
**regardless of this user's access level** — reading the published index
never requires write access, and it's exactly what lets a read-only user
skip building anything themselves.
If `source.yaml` has an `index:` block, check whether `index.location`
already has a published index (per `index.store`: a `git` remote with
commits/a reachable ref, or a filesystem/network/`shared` location with
files already in it):
- **It exists** → fetch/pull it (`git pull`/clone for `git`, a plain file
copy for a filesystem/network `shared` path, or the matching connector
tool for a `shared` location that needs one) and use it to refresh
`libs/<name>/{index.md,entities/,graph/,log.md}`. Do this **regardless
of this user's access level** — reading the published index never
requires write access, and it's exactly what lets a read-only user skip
building anything themselves.
- **It's empty / nothing published yet** → there's nothing to fetch. Don't
treat this as an error; it's the normal first-time state before anyone
with write access has run this. Continue to Step 4 — whether that turns
into "create it" or "nothing to report" depends entirely on this user's
access level.
If no `index:` block is configured, there's nothing to fetch — the index
(if any exists yet) already lives directly in `libs/<name>/`, same as
before.
If no `index:` block is configured at all, skip this check — the index (if
any exists yet) already lives directly in `libs/<name>/`, same as before.
### Step 4 — Decide whether to build or refresh from the live connector
This is the one place access level actually changes behavior:
- **Read-only** (the common case, and the default for anyone who hasn't
set `access: write` locally): stop here. Report what the fetched/existing
index already covers. If nothing has ever been indexed for this source
and this user is read-only, say so plainly — don't scan the live
connector on their behalf. Suggest asking whoever administers this
source to run it, or setting `access: write` locally if this user is
meant to be that admin.
- **Write access**: continue to Step 5 and actually build/refresh the
index from the live connector `location`.
set `access: write` locally): stop here, regardless of what Step 3
found. Never touch the live connector on a read-only user's behalf.
- If Step 3 fetched something (or one already lived in `libs/<name>/`
with no `index:` block): report what it covers.
- If nothing exists anywhere yet (Step 3 found the shared store empty,
or there's no `index:` block and `libs/<name>/` is empty too): say so
plainly, and suggest asking whoever administers this source to run it,
or setting `access: write` locally if this user is meant to be that
admin.
- **Write access**: always continue to Step 5, whether Step 3 fetched an
existing index (refresh it) or found the store empty (build the very
first version from scratch) — the two cases are handled identically
from here on; Step 7 is what actually creates the remote copy either
way.
### Step 5 — Resolve the connector and enumerate/summarize documents
@ -215,11 +232,22 @@ If this user has `access: write` **and** `source.yaml` has an `index:`
block, push the refreshed `libs/<name>/{index.md,entities/,graph/,log.md}`
back out to `index.location` (`git push` for `store: git`, a file copy
back for a filesystem/network `store: shared` path, or the matching
connector tool for a `shared` location that needs one) — so every other
user's next fetch (Step 3) picks up the update. If no `index:` block is
configured, there's nothing to publish; the refreshed files staying inside
this repo's own `libs/<name>/` (tracked by this repo's own git) *is* the
publish step, same as the original default behavior.
connector tool for a `shared` location that needs one) — **every single
run**, not just the first one, so every other user's next fetch (Step 3)
picks up the update. This is exactly how a shared index gets created in
the first place: if Step 3 found the store empty, this step's push is what
populates it for the first time; there's no separate "initialize" action.
If no `index:` block is configured, there's nothing external to publish;
the refreshed files staying inside this repo's own `libs/<name>/` (tracked
by this repo's own git) *is* the publish step, same as the original
default behavior.
If this user is **read-only**, this step never runs — nothing is ever
pushed or copied to `index.location` (or, in the no-`index:`-block case,
nothing is even rebuilt in `libs/<name>/` to begin with). A read-only user
has, by construction, nothing of their own to save back — Step 4 already
stopped them before anything was built.
### Step 8 — Remind to review and sync