Issue 274: a provider is granted only the consumers bound to it

This commit is contained in:
jochen
2026-10-06 16:08:30 +02:00
parent f197fcf146
commit c818e9c766
@@ -0,0 +1,103 @@
---
status: located
opened: 2026-10-06
located-in: [mesh-controller]
fixed-by: novox/mesh-controller PR #87
amended-design:
---
# 274. A provider was granted consumers bound elsewhere
## Symptom
After [issue 273](../273-a-rule-for-the-resolver-moved-a-machines-databases/00-report.md), the five
applications on the home server were pinned back to the home server's own store. They run there, on
their own data. The operator confirmed it and asked for the databases made for them on the control
node's store to be retired:
[ADR 0230](../../02-DECISIONS/0230-a-consumer-the-mesh-stops-asking-for-is-retired-and-deleted-only-by-a-person.md)
disables them, keeps their data, and leaves deleting them to a person.
They were never retired. Read on 2026-10-06, without changing anything:
- The control node's plan still carried a grant file for each of the five, one per consumer of the
relational database provision on the home server.
- The control node's database provider still counted all five as asked for. It listed them as held,
and nothing was waiting on a retirement.
- Each consumer's own resolution bound it to the home server's store, and its binding file said so.
The mesh asked one provider to keep five logins for consumers bound to another. Nothing said so.
Under ADR 0230, the provider retires only what the mesh stops asking for, so it would have kept them
forever.
## Cause
Which consumers a provider is granted was read from the wrong record. The controller enumerated every
pair credential on record from the provider. It granted each one whose consumer still *required* the
provision. It never checked *which provider* that requirement was bound to.
A pair credential records that the provider was asked by a consumer once. It does not record that it
is still asked. The issue 273 move made a credential from the control node for each of the five. The
pin back made the consumers use the home server's credential again. The control node's credentials
stayed on record, so the control node stayed granted.
Before issue 273 this gap had no visible effect: only a person moves a consumer, and it is rare.
[ADR 0232](../../02-DECISIONS/0232-a-binding-to-a-consumers-data-moves-only-by-a-person.md) makes
a pin the only way to move a consumer of a provision that keeps data. That makes this the path every
such move takes, and every move left a provider granted a consumer it no longer serves.
## Fix
The fix is novox/mesh-controller PR #87. **A provider is granted exactly the consumers whose own
current resolution binds them to it.** A credential is identified by its provision, the consuming
module and its local name.
- A consumer that still asks, but whose resolution binds that credential to another provider (or,
under that local name, to none), is withdrawn exactly like a consumer nobody asks for. The provider
is no longer told about it, sees it unasked, and retires it under ADR 0230 with its data kept.
- The withdrawal is reported. The provider's `plan` and `push` name each such consumer, where it is
bound now, and that the login is retired and its data kept until `cleanup delete`.
- **The pair credential is kept on record, not forgotten.** It is the key to the login the provider
still holds, disabled, beside the consumer's data. A person who pins the consumer back finds it.
Dropping it while the provider holds that login would make a pin back mint a new credential for
data the old one owns.
- The binding is read from the same resolution the grant was already read from. An unreadable
resolution stays an error, never an empty answer
([issue 152](../152-a-nodes-plan-failure-silently-drops-its-routed-names/00-report.md)). A kept
binding (ADR 0232) is a resolution binding the consumer to its recorded provider, so that provider
keeps the grant.
[ADR 0225](../../02-DECISIONS/0225-a-consumers-identity-is-bounded-by-the-provision-it-requires.md)'s
overflow check applies to what is still granted.
After rollout, the five become unasked on the control node's provider. After five passes they are
candidates for retirement. Five is more than the provider's bound of three, so it retires nothing,
and the controller raises an urgent *retire-waiting* condition that names them. The operator answers
it with `retire approve`.
## How it is checked
Tests in the controller run through its real stores.
- **Today's state.** A consumer is pinned to another machine's store and sent. It is then pinned back
beside its data, so a credential from each store is on record. The store it left no longer grants
it, its declaration no longer carries it, and the push names it. The store it is bound to grants
it. Both credentials stay on record. This test fails without the fix.
- **An unreadable resolution.** A consumer whose resolution cannot be completed makes the grants an
error, not a withdrawal.
- **The rule on a resolution.** A credential is bound to the provider of a need for exactly that
credential. A need answered by a record binds nothing, and another local name is another
credential.
## Left open
- **When a kept credential is forgotten.** It should be dropped once the provider reports that
consumer deleted by `cleanup delete`. Nothing connects the two yet, so these credentials stay on
record after the data is gone. They are reported on every plan of the provider until then.
- **`rotate` and a credential bound elsewhere.** Rotating the provision for one of these consumers
still lists both holders. Rotating the unbound one discards it, and nothing remakes it, because no
need is bound there. That is harmless, since its provider is no longer granted it, but it is the
one path that forgets such a credential, and it does so without saying why.
- **A consumer whose set does not resolve.** Its grants are skipped, not kept: the existing rule that
a set that does not resolve is that machine's problem. Under ADR 0230, a provider then sees that
consumer unasked and, after five passes, retires it, so a broken set elsewhere can retire a working
consumer's login. The retirement bound and the person's approval limit the damage, but this is the
same class of withdrawal-on-a-failed-read as issue 152, and it should be decided on its own.