Merge pull request 'Issue 274: a provider is granted only the consumers bound to it' (#138) from issues/274-a-provider-was-granted-consumers-bound-elsewhere into main
mesh/delivery held for a person: merged without a passing check: only a person decides that it goes on
mesh/delivery held for a person: merged without a passing check: only a person decides that it goes on
This commit was merged in pull request #138.
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user