Resync hq ADR references (0044-0054 -> 0039-0049) #6
@@ -198,7 +198,7 @@ func moduleCommand(ctx context.Context, args []string) error {
|
|||||||
return nil
|
return nil
|
||||||
|
|
||||||
case "issue":
|
case "issue":
|
||||||
// A module's broker account, scoped by its emits and consumes (novox/hq ADR 0048) and
|
// A module's broker account, scoped by its emits and consumes (novox/hq ADR 0043) and
|
||||||
// sealed to the machine that will run it — the generic case the builder was the first of.
|
// sealed to the machine that will run it — the generic case the builder was the first of.
|
||||||
set := flag.NewFlagSet("module issue", flag.ContinueOnError)
|
set := flag.NewFlagSet("module issue", flag.ContinueOnError)
|
||||||
forNode := set.String("node", "",
|
forNode := set.String("node", "",
|
||||||
@@ -244,7 +244,7 @@ func moduleCommand(ctx context.Context, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// A consumer's queue, with its dead-letter, is the substrate's to declare — its own account
|
// A consumer's queue, with its dead-letter, is the substrate's to declare — its own account
|
||||||
// may not (ADR 0048). Made now, so it exists before the module binds onto it.
|
// may not (ADR 0043). Made now, so it exists before the module binds onto it.
|
||||||
if len(m.Consumes) > 0 {
|
if len(m.Consumes) > 0 {
|
||||||
if err := management.EnsureModuleQueue(ctx, *forNode, module); err != nil {
|
if err := management.EnsureModuleQueue(ctx, *forNode, module); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -521,7 +521,7 @@ func grantsFor(ctx context.Context, open *stores, node string) ([]catalogue.Gran
|
|||||||
from = ""
|
from = ""
|
||||||
}
|
}
|
||||||
// The consumer's identity slug, from its own manifest, carried on the grant so the provider
|
// The consumer's identity slug, from its own manifest, carried on the grant so the provider
|
||||||
// derives the same login the consumer does (novox/hq ADR 0054). Refused here if it still would
|
// derives the same login the consumer does (novox/hq ADR 0049). Refused here if it still would
|
||||||
// not fit the tightest backend — the mesh chose the name, so the mesh refuses it, with the
|
// not fit the tightest backend — the mesh chose the name, so the mesh refuses it, with the
|
||||||
// remedy a short slug rather than a login a provider silently shortened.
|
// remedy a short slug rather than a login a provider silently shortened.
|
||||||
slug := ""
|
slug := ""
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ const ExchangeName = "mesh"
|
|||||||
// constant that differed would be caught by the test that asserts they agree.
|
// constant that differed would be caught by the test that asserts they agree.
|
||||||
const BuildQueueName = "builds"
|
const BuildQueueName = "builds"
|
||||||
|
|
||||||
// The events bus (novox/hq ADR 0047): one topic exchange every event rides, a second for tool
|
// The events bus (novox/hq ADR 0042): one topic exchange every event rides, a second for tool
|
||||||
// RPC kept apart, and a dead-letter home for a poison event. The substrate owns these — a module's
|
// RPC kept apart, and a dead-letter home for a poison event. The substrate owns these — a module's
|
||||||
// account cannot declare them, only bind its own queue to the events one.
|
// account cannot declare them, only bind its own queue to the events one.
|
||||||
const (
|
const (
|
||||||
@@ -77,15 +77,15 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ModuleQueueFor is the durable queue a module consumes its events from — one per module per node
|
// ModuleQueueFor is the durable queue a module consumes its events from — one per module per node
|
||||||
// (novox/hq ADR 0047), named so the account that may read it is exactly this module's.
|
// (novox/hq ADR 0042), named so the account that may read it is exactly this module's.
|
||||||
func ModuleQueueFor(node, module string) string { return node + "." + module + ".events" }
|
func ModuleQueueFor(node, module string) string { return node + "." + module + ".events" }
|
||||||
|
|
||||||
// modulePermissions is a module's authority on the bus, derived from its manifest (novox/hq
|
// modulePermissions is a module's authority on the bus, derived from its manifest (novox/hq
|
||||||
// ADR 0048): what it consumes and what it emits, and nothing else. Pure, so the scope is tested as
|
// ADR 0043): what it consumes and what it emits, and nothing else. Pure, so the scope is tested as
|
||||||
// patterns without a broker — the way a builder's is.
|
// patterns without a broker — the way a builder's is.
|
||||||
//
|
//
|
||||||
// A note on the limit: the broker's write permission is per exchange, not per routing key (LavinMQ
|
// A note on the limit: the broker's write permission is per exchange, not per routing key (LavinMQ
|
||||||
// has no topic permissions), so an emitting module is granted the events exchange whole. ADR 0047's
|
// has no topic permissions), so an emitting module is granted the events exchange whole. ADR 0042's
|
||||||
// origin reservation — a module publishes only under `module.<self>.*` — is stamped by the sdk, not
|
// origin reservation — a module publishes only under `module.<self>.*` — is stamped by the sdk, not
|
||||||
// enforced here; that gap is the broker's, and is recorded rather than hidden. A pure consumer like
|
// enforced here; that gap is the broker's, and is recorded rather than hidden. A pure consumer like
|
||||||
// the audit logger is unaffected: it is granted no write to the exchange at all.
|
// the audit logger is unaffected: it is granted no write to the exchange at all.
|
||||||
@@ -94,7 +94,7 @@ func modulePermissions(node, module string, emits, consumes []string) (configure
|
|||||||
events := regexp.QuoteMeta(EventsExchangeName)
|
events := regexp.QuoteMeta(EventsExchangeName)
|
||||||
rpc := regexp.QuoteMeta(RPCExchangeName)
|
rpc := regexp.QuoteMeta(RPCExchangeName)
|
||||||
// A module serves each of its tools on its own queue, namespaced by the module (novox/hq
|
// A module serves each of its tools on its own queue, namespaced by the module (novox/hq
|
||||||
// ADR 0052) — serve.<module>.<tool> — so the account may declare, bind and read exactly its own,
|
// ADR 0047) — serve.<module>.<tool> — so the account may declare, bind and read exactly its own,
|
||||||
// and no other module's.
|
// and no other module's.
|
||||||
serve := "serve\\." + regexp.QuoteMeta(module) + "\\..*"
|
serve := "serve\\." + regexp.QuoteMeta(module) + "\\..*"
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ func modulePermissions(node, module string, emits, consumes []string) (configure
|
|||||||
configure = "^(" + queue + "|" + serve + ")$"
|
configure = "^(" + queue + "|" + serve + ")$"
|
||||||
|
|
||||||
// Write to bind its queue and serve queues (binding is a write on the queue), and to the RPC
|
// Write to bind its queue and serve queues (binding is a write on the queue), and to the RPC
|
||||||
// exchange to publish replies (ADR 0052: replies ride mesh.rpc, never the default exchange, which
|
// exchange to publish replies (ADR 0047: replies ride mesh.rpc, never the default exchange, which
|
||||||
// would let it publish into any queue). To the events exchange only if it emits.
|
// would let it publish into any queue). To the events exchange only if it emits.
|
||||||
writes := []string{queue, serve, rpc}
|
writes := []string{queue, serve, rpc}
|
||||||
if len(emits) > 0 {
|
if len(emits) > 0 {
|
||||||
@@ -121,7 +121,7 @@ func modulePermissions(node, module string, emits, consumes []string) (configure
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateModuleAccount gives an assigned module its own broker account, scoped by what it emits and
|
// CreateModuleAccount gives an assigned module its own broker account, scoped by what it emits and
|
||||||
// consumes (novox/hq ADR 0048). The account name carries the node so the same module on two machines
|
// consumes (novox/hq ADR 0043). The account name carries the node so the same module on two machines
|
||||||
// holds two accounts, each sealed to its own; the permissions carry the module so one module cannot
|
// holds two accounts, each sealed to its own; the permissions carry the module so one module cannot
|
||||||
// read another's queue. Generic — the builder is one instance of this rule, not a separate kind.
|
// read another's queue. Generic — the builder is one instance of this rule, not a separate kind.
|
||||||
func (m *Management) CreateModuleAccount(ctx context.Context, node, module, password string, emits, consumes []string) (string, error) {
|
func (m *Management) CreateModuleAccount(ctx context.Context, node, module, password string, emits, consumes []string) (string, error) {
|
||||||
@@ -152,7 +152,7 @@ func (m *Management) CreateModuleAccount(ctx context.Context, node, module, pass
|
|||||||
|
|
||||||
// EnsureModuleQueue declares a consuming module's queue with its dead-letter exchange, idempotently.
|
// EnsureModuleQueue declares a consuming module's queue with its dead-letter exchange, idempotently.
|
||||||
// The substrate declares it because a scoped module account may not: the broker refuses a queue with
|
// The substrate declares it because a scoped module account may not: the broker refuses a queue with
|
||||||
// a dead-letter exchange to a non-administrator (novox/hq ADR 0048), so a consumer passively checks
|
// a dead-letter exchange to a non-administrator (novox/hq ADR 0043), so a consumer passively checks
|
||||||
// the queue the mesh made rather than declaring its own.
|
// the queue the mesh made rather than declaring its own.
|
||||||
func (m *Management) EnsureModuleQueue(ctx context.Context, node, module string) error {
|
func (m *Management) EnsureModuleQueue(ctx context.Context, node, module string) error {
|
||||||
queue := ModuleQueueFor(node, module)
|
queue := ModuleQueueFor(node, module)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
|
|
||||||
// The audit logger consumes everything and emits nothing. Its account must let it declare and read
|
// The audit logger consumes everything and emits nothing. Its account must let it declare and read
|
||||||
// its own queue and read the events exchange to bind onto — and must not reach another module's
|
// its own queue and read the events exchange to bind onto — and must not reach another module's
|
||||||
// queue, nor grant any write to the events exchange (novox/hq ADR 0048).
|
// queue, nor grant any write to the events exchange (novox/hq ADR 0043).
|
||||||
func TestAConsumerReadsItsOwnQueueAndTheEventsExchangeAndNoOthers(t *testing.T) {
|
func TestAConsumerReadsItsOwnQueueAndTheEventsExchangeAndNoOthers(t *testing.T) {
|
||||||
// Rebuilt through CreateModuleAccount's own path by asking for the same scope it would apply.
|
// Rebuilt through CreateModuleAccount's own path by asking for the same scope it would apply.
|
||||||
// The queue this module reads:
|
// The queue this module reads:
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ type Grant struct {
|
|||||||
Values map[string]any
|
Values map[string]any
|
||||||
// Slug is the consumer module's identity slug, if it declared one — carried on the grant so the
|
// Slug is the consumer module's identity slug, if it declared one — carried on the grant so the
|
||||||
// provider side derives the same login the consumer does, even across nodes where the consumer's
|
// provider side derives the same login the consumer does, even across nodes where the consumer's
|
||||||
// manifest is not in view (novox/hq ADR 0054). Empty means "use the module name".
|
// manifest is not in view (novox/hq ADR 0049). Empty means "use the module name".
|
||||||
Slug string
|
Slug string
|
||||||
// At is where the consuming machine is on the private network, empty if it is not on one.
|
// At is where the consuming machine is on the private network, empty if it is not on one.
|
||||||
//
|
//
|
||||||
@@ -143,7 +143,7 @@ func (r Resolution) Declaration(with Rendering) ([]map[string]any, error) {
|
|||||||
|
|
||||||
// Once, from every module's listens -- not per module. A module receiving only its own ports
|
// Once, from every module's listens -- not per module. A module receiving only its own ports
|
||||||
// would write a rule set that closed every other module on the machine. Each module's per-node
|
// would write a rule set that closed every other module on the machine. Each module's per-node
|
||||||
// exposure settings override its listens' source first (novox/hq ADR 0051).
|
// exposure settings override its listens' source first (novox/hq ADR 0046).
|
||||||
exposure := map[string]map[int]string{}
|
exposure := map[string]map[int]string{}
|
||||||
for _, m := range r.Modules {
|
for _, m := range r.Modules {
|
||||||
e, err := Exposure(m, with.Settings[m.Module])
|
e, err := Exposure(m, with.Settings[m.Module])
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ func (r Resolution) Filtering(computed map[string]Generator, ports map[string]ma
|
|||||||
}
|
}
|
||||||
// The source, with any per-node exposure setting applied. The override names the port
|
// The source, with any per-node exposure setting applied. The override names the port
|
||||||
// the module declares, so it travels with that port to wherever the machine publishes
|
// the module declares, so it travels with that port to wherever the machine publishes
|
||||||
// it (novox/hq ADR 0051): the same module is internal on one node and public on another.
|
// it (novox/hq ADR 0046): the same module is internal on one node and public on another.
|
||||||
from := l.From
|
from := l.From
|
||||||
if override, set := exposure[m.Module][l.Port]; set {
|
if override, set := exposure[m.Module][l.Port]; set {
|
||||||
from = override
|
from = override
|
||||||
@@ -108,7 +108,7 @@ func (r Resolution) Filtering(computed map[string]Generator, ports map[string]ma
|
|||||||
return widest(out), nil
|
return widest(out), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExposeSetting is the settings key that overrides a listen's source per node (novox/hq ADR 0051):
|
// ExposeSetting is the settings key that overrides a listen's source per node (novox/hq ADR 0046):
|
||||||
//
|
//
|
||||||
// {"expose": {"5432": "anywhere"}}
|
// {"expose": {"5432": "anywhere"}}
|
||||||
//
|
//
|
||||||
@@ -122,7 +122,7 @@ const ExposeSetting = "expose"
|
|||||||
// It refuses an override for a port the module does not listen on, or to a source that is not a
|
// It refuses an override for a port the module does not listen on, or to a source that is not a
|
||||||
// real one — an exposure setting that reaches no port, or names a source nothing enforces, is the
|
// real one — an exposure setting that reaches no port, or names a source nothing enforces, is the
|
||||||
// "reads as a restriction and is none" fault this whole mechanism exists to prevent (novox/hq
|
// "reads as a restriction and is none" fault this whole mechanism exists to prevent (novox/hq
|
||||||
// ADR 0048/0050). A module with no `expose` setting yields nothing and keeps its manifest defaults.
|
// ADR 0043/0045). A module with no `expose` setting yields nothing and keeps its manifest defaults.
|
||||||
func Exposure(m Manifest, layers []Layer) (map[int]string, error) {
|
func Exposure(m Manifest, layers []Layer) (map[int]string, error) {
|
||||||
listened := make(map[int]bool, len(m.Listens))
|
listened := make(map[int]bool, len(m.Listens))
|
||||||
for _, l := range m.Listens {
|
for _, l := range m.Listens {
|
||||||
|
|||||||
@@ -580,7 +580,7 @@ func named(r Resolution) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A port's source is a per-node setting, not a manifest constant: the same module is internal on
|
// A port's source is a per-node setting, not a manifest constant: the same module is internal on
|
||||||
// one machine and public on another (novox/hq ADR 0051). postgres listens from the mesh by default;
|
// one machine and public on another (novox/hq ADR 0046). postgres listens from the mesh by default;
|
||||||
// a setting on one node exposes it to anywhere, and the rule set follows.
|
// a setting on one node exposes it to anywhere, and the rule set follows.
|
||||||
func TestExposureSettingOverridesAListensSource(t *testing.T) {
|
func TestExposureSettingOverridesAListensSource(t *testing.T) {
|
||||||
postgres := Manifest{Module: "postgres", Version: "1",
|
postgres := Manifest{Module: "postgres", Version: "1",
|
||||||
@@ -605,7 +605,7 @@ func TestExposureSettingOverridesAListensSource(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Exposure refuses a setting that names a port the module does not listen on, or a source that is
|
// Exposure refuses a setting that names a port the module does not listen on, or a source that is
|
||||||
// not a real one — a setting reaching nothing is worse than none (novox/hq ADR 0048/0051).
|
// not a real one — a setting reaching nothing is worse than none (novox/hq ADR 0043/0046).
|
||||||
func TestExposureRefusesAPortNotListenedOnAndABadSource(t *testing.T) {
|
func TestExposureRefusesAPortNotListenedOnAndABadSource(t *testing.T) {
|
||||||
postgres := Manifest{Module: "postgres", Listens: []Listening{{Port: 5432, From: FromMesh}}}
|
postgres := Manifest{Module: "postgres", Listens: []Listening{{Port: 5432, From: FromMesh}}}
|
||||||
layer := func(port, source string) []Layer {
|
layer := func(port, source string) []Layer {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ var identityUnusable = regexp.MustCompile(`[^a-z0-9_]+`)
|
|||||||
const IdentityPrefix = "mesh_"
|
const IdentityPrefix = "mesh_"
|
||||||
|
|
||||||
// IdentitySource is the name the mesh derives a consumer's identity from: the module's slug when it
|
// IdentitySource is the name the mesh derives a consumer's identity from: the module's slug when it
|
||||||
// has declared one, otherwise its name (novox/hq ADR 0054). A module with a name short enough to fit
|
// has declared one, otherwise its name (novox/hq ADR 0049). A module with a name short enough to fit
|
||||||
// the tightest backend needs no slug; one whose name would overflow declares a short legible one.
|
// the tightest backend needs no slug; one whose name would overflow declares a short legible one.
|
||||||
func IdentitySource(slug, name string) string {
|
func IdentitySource(slug, name string) string {
|
||||||
if slug != "" {
|
if slug != "" {
|
||||||
@@ -59,7 +59,7 @@ func ConsumerIdentity(node, module string) string {
|
|||||||
// identityLimit is the shortest identifier limit among the systems these names reach: an S3 access
|
// identityLimit is the shortest identifier limit among the systems these names reach: an S3 access
|
||||||
// key's 20 (novox/hq 04-ISSUES/010). PostgreSQL keeps 63 and MinIO 20, so 20 is the one that binds —
|
// key's 20 (novox/hq 04-ISSUES/010). PostgreSQL keeps 63 and MinIO 20, so 20 is the one that binds —
|
||||||
// the comment used to name PostgreSQL and was wrong. A name over it is refused, with the remedy a
|
// the comment used to name PostgreSQL and was wrong. A name over it is refused, with the remedy a
|
||||||
// short slug (ADR 0054), not silently cut to fit.
|
// short slug (ADR 0049), not silently cut to fit.
|
||||||
const identityLimit = 20
|
const identityLimit = 20
|
||||||
|
|
||||||
// CheckIdentity refuses an identity that would not fit the tightest backend a consumer reaches.
|
// CheckIdentity refuses an identity that would not fit the tightest backend a consumer reaches.
|
||||||
@@ -68,7 +68,7 @@ const identityLimit = 20
|
|||||||
// the statement succeeds, so two consumers agreeing for the first N bytes would become one login
|
// the statement succeeds, so two consumers agreeing for the first N bytes would become one login
|
||||||
// (04-ISSUES/022) — and S3 refuses outright. Refused here, at the mesh, because the mesh chose the
|
// (04-ISSUES/022) — and S3 refuses outright. Refused here, at the mesh, because the mesh chose the
|
||||||
// name and is the only thing that can choose another. The remedy is a first-class one: give the
|
// name and is the only thing that can choose another. The remedy is a first-class one: give the
|
||||||
// module a short `slug` (ADR 0054), or shorten the machine's name.
|
// module a short `slug` (ADR 0049), or shorten the machine's name.
|
||||||
func CheckIdentity(node, module string) error {
|
func CheckIdentity(node, module string) error {
|
||||||
got := ConsumerIdentity(node, module)
|
got := ConsumerIdentity(node, module)
|
||||||
if len(got) <= identityLimit {
|
if len(got) <= identityLimit {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import "testing"
|
|||||||
|
|
||||||
func TestASlugIsPreferredOverTheModuleName(t *testing.T) {
|
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
|
// 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).
|
// tightest backend without a hash (novox/hq ADR 0049).
|
||||||
if got := IdentitySource("kc", "keycloak"); got != "kc" {
|
if got := IdentitySource("kc", "keycloak"); got != "kc" {
|
||||||
t.Errorf("the slug was not preferred: %q", got)
|
t.Errorf("the slug was not preferred: %q", got)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ type Manifest struct {
|
|||||||
Version string `json:"version,omitempty"`
|
Version string `json:"version,omitempty"`
|
||||||
|
|
||||||
// Slug is a short identifier the mesh uses in place of the module name when it derives a
|
// Slug is a short identifier the mesh uses in place of the module name when it derives a
|
||||||
// consumer's login (novox/hq ADR 0054). Optional: a module with a short name needs none. It
|
// consumer's login (novox/hq ADR 0049). Optional: a module with a short name needs none. It
|
||||||
// exists because `mesh_<node>_<module>` must fit the tightest backend a consumer reaches — an S3
|
// exists because `mesh_<node>_<module>` must fit the tightest backend a consumer reaches — an S3
|
||||||
// access key is 20 characters — and a long module name would overflow it. A person choosing
|
// access key is 20 characters — and a long module name would overflow it. A person choosing
|
||||||
// `kc` for keycloak keeps the identity legible where a hash would not.
|
// `kc` for keycloak keeps the identity legible where a hash would not.
|
||||||
@@ -135,7 +135,7 @@ type Manifest struct {
|
|||||||
|
|
||||||
// Emits are the event types this module publishes onto the broker — dotted topic keys, e.g.
|
// Emits are the event types this module publishes onto the broker — dotted topic keys, e.g.
|
||||||
// "module.umami.site.created". Declared so the mesh knows the event graph; events are
|
// "module.umami.site.created". Declared so the mesh knows the event graph; events are
|
||||||
// provisioning's lighter sibling — 1:many and broadcast, no credential (novox/hq ADR 0046).
|
// provisioning's lighter sibling — 1:many and broadcast, no credential (novox/hq ADR 0041).
|
||||||
Emits []string `json:"emits,omitempty"`
|
Emits []string `json:"emits,omitempty"`
|
||||||
|
|
||||||
// Consumes are the event patterns this module subscribes to — topic patterns over module,
|
// Consumes are the event patterns this module subscribes to — topic patterns over module,
|
||||||
@@ -474,7 +474,7 @@ func ParseManifest(raw []byte) (Manifest, error) {
|
|||||||
problems = append(problems, fmt.Sprintf(
|
problems = append(problems, fmt.Sprintf(
|
||||||
"%q is not a usable module name: lower-case letters, digits, dashes and dots", m.Module))
|
"%q is not a usable module name: lower-case letters, digits, dashes and dots", m.Module))
|
||||||
}
|
}
|
||||||
// A slug is a short identifier the mesh derives a login from (novox/hq ADR 0054). The same
|
// A slug is a short identifier the mesh derives a login from (novox/hq ADR 0049). The same
|
||||||
// charset as a name; its length is checked against a backend's limit at assignment, where the
|
// charset as a name; its length is checked against a backend's limit at assignment, where the
|
||||||
// node it joins is known — a slug that is fine on one machine's short name can overflow another's.
|
// node it joins is known — a slug that is fine on one machine's short name can overflow another's.
|
||||||
if m.Slug != "" && !name.MatchString(m.Slug) {
|
if m.Slug != "" && !name.MatchString(m.Slug) {
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ func UnusedSettings(m Manifest, layers []Layer) []string {
|
|||||||
for _, layer := range layers {
|
for _, layer := range layers {
|
||||||
for key := range layer.Values {
|
for key := range layer.Values {
|
||||||
// `expose` is a real destination for a module that listens: it overrides a port's
|
// `expose` is a real destination for a module that listens: it overrides a port's
|
||||||
// source (novox/hq ADR 0051), validated in Exposure, so it is not stray here.
|
// source (novox/hq ADR 0046), validated in Exposure, so it is not stray here.
|
||||||
if key == ExposeSetting && len(m.Listens) > 0 {
|
if key == ExposeSetting && len(m.Listens) > 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func Make(consumerKey, providerKey string) (Sealed, error) {
|
|||||||
|
|
||||||
// 30 bytes, not 32: base64url of 30 is exactly 40 characters, and 40 is the longest secret an
|
// 30 bytes, not 32: base64url of 30 is exactly 40 characters, and 40 is the longest secret an
|
||||||
// S3 access key accepts (8–40), the tightest of the backends a minted password reaches — the same
|
// S3 access key accepts (8–40), the tightest of the backends a minted password reaches — the same
|
||||||
// "fit the tightest backend" rule ADR 0054 sets for the login, on the secret. 240 bits is ample.
|
// "fit the tightest backend" rule ADR 0049 sets for the login, on the secret. 240 bits is ample.
|
||||||
value := make([]byte, 30)
|
value := make([]byte, 30)
|
||||||
if _, err := rand.Read(value); err != nil {
|
if _, err := rand.Read(value); err != nil {
|
||||||
return Sealed{}, err
|
return Sealed{}, err
|
||||||
|
|||||||
Reference in New Issue
Block a user