-- A credential belongs to a consumer, and a consumer is a module on a machine. -- -- novox/hq 04-ISSUES/022. The key was (provision, consumer node, provider node), so "who is -- asking" was answered by naming a host. A node running three modules against one database server -- had one credential between them: the provisioner created one role, `mesh_`, owning every -- database it was asked for, and gitea's login opened keycloak's data. Nothing anywhere would -- have said so -- from the provisioner's side it created exactly what it was asked to create. -- -- **Two modules on one node are as separate as two on different nodes.** They are different -- containers, on different networks, with different data. This is the same correction as 021, -- which found the machine wrongly treated as a trust boundary; here it was wrongly treated as an -- identity. -- -- It also restores withdrawal. One role per node cannot express "this module no longer has a -- login and the others still do", so a consumer that went away kept a working credential for as -- long as any other consumer on that machine remained. alter table secret add column consumer_module text references module(name) on delete cascade; -- Existing rows cannot say which module they were for, because at the time nothing recorded it. -- -- **Discarded rather than guessed.** A secret is remade on the next declaration and reaches both -- ends in the same push, which is exactly what rotation does -- so this costs one rotation and -- nothing else. Backfilling with "whichever module resolves first" would be inventing an answer -- to the question this migration exists because nobody could answer. delete from secret; alter table secret alter column consumer_module set not null; alter table secret drop constraint secret_pkey; alter table secret add primary key (name, consumer, consumer_module, provider);