A module may declare a short `slug`; the mesh derives mesh_<node>_<slug|name> and refuses at assignment (naming the slug as the remedy) when it would still overflow — identityLimit is now 20, an S3 access key's, the tightest of the backends a login reaches (04-ISSUES/010). The slug rides the grant so the provider derives the same login the consumer does, even across nodes. CheckIdentity is now wired, in grantsFor. Also, the minted secret shrinks to 40 chars (30 bytes) from 43: an S3 secret key is 8-40, the same fit-the-tightest-backend rule on the credential's other half. Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
54 lines
1.8 KiB
Go
54 lines
1.8 KiB
Go
package catalogue
|
|
|
|
import "testing"
|
|
|
|
// Each test names the decision it defends (novox/hq ADR 0017).
|
|
|
|
func TestASlugIsPreferredOverTheModuleName(t *testing.T) {
|
|
// A module that declared a slug is identified by it, so a long name can be made to fit the
|
|
// tightest backend without a hash (novox/hq ADR 0054).
|
|
if got := IdentitySource("kc", "keycloak"); got != "kc" {
|
|
t.Errorf("the slug was not preferred: %q", got)
|
|
}
|
|
if got := IdentitySource("", "redis"); got != "redis" {
|
|
t.Errorf("without a slug, the name should be used: %q", got)
|
|
}
|
|
if ConsumerIdentity("anchor", IdentitySource("bkt", "bucketuser")) != "mesh_anchor_bkt" {
|
|
t.Error("a slug did not shape the identity")
|
|
}
|
|
}
|
|
|
|
func TestCheckIdentityFitsTheTightestBackend(t *testing.T) {
|
|
// 20 is an S3 access key's limit (04-ISSUES/010), and the one that binds. mesh_anchor_keycloak
|
|
// is exactly 20 and allowed; the un-slugged bucketuser is 22 and refused, with the remedy a slug.
|
|
if err := CheckIdentity("anchor", "keycloak"); err != nil { // mesh_anchor_keycloak = 20
|
|
t.Errorf("a 20-character identity was refused: %v", err)
|
|
}
|
|
if err := CheckIdentity("anchor", "bucketuser"); err == nil { // mesh_anchor_bucketuser = 22
|
|
t.Error("an over-long identity was accepted")
|
|
}
|
|
// But with a slug it fits, and is accepted.
|
|
if err := CheckIdentity("anchor", IdentitySource("bkt", "bucketuser")); err != nil {
|
|
t.Errorf("a slugged identity that fits was refused: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestTheRefusalNamesTheRemedy(t *testing.T) {
|
|
err := CheckIdentity("anchor", "bucketuser")
|
|
if err == nil {
|
|
t.Fatal("expected a refusal")
|
|
}
|
|
if !contains(err.Error(), "slug") {
|
|
t.Errorf("the refusal did not point at the slug as the remedy: %v", err)
|
|
}
|
|
}
|
|
|
|
func contains(s, sub string) bool {
|
|
for i := 0; i+len(sub) <= len(s); i++ {
|
|
if s[i:i+len(sub)] == sub {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|