// Package orgctx carries the organization a request operates on. // // It predates authentication. Before there was a session to derive a tenant // from, org_id was put on the request context by one middleware rather than // defaulted deep inside the SQL, so that it would not have to be unpicked from // fourteen repositories later. That handover has since happened: the // authenticate middleware in httpserver reads the organization off the user's // row, and authctx.Identity.OrgID is what the service and repository layers // actually read. // // What is still load-bearing here is DevOrgSlug and DevOrgName, which name the // organization the seeder creates. With and From remain the read/write pair for // the context key the middleware still sets; retiring them in favour of // authctx.Identity.OrgID alone is a deliberate change, not a tidy-up. package orgctx import ( "context" "errors" ) type key struct{} // DevOrgSlug identifies the single organization every Phase 2C request runs as. // The seeder creates it; nothing else does. // // THIS IS NOT AUTHENTICATION. It is a fixed development identity with no // credential, no session and no verification behind it. const DevOrgSlug = "krow-dev" // DevOrgName is that organization's display name. const DevOrgName = "Krow Development" // ErrNoOrg means the context reached a scoped operation without an organization, // which is a programming error rather than a client one. var ErrNoOrg = errors.New("no organization in context") // With returns a context carrying an organization id. func With(ctx context.Context, orgID string) context.Context { return context.WithValue(ctx, key{}, orgID) } // From reads the organization id, reporting whether one was present. func From(ctx context.Context) (string, bool) { v, ok := ctx.Value(key{}).(string) return v, ok && v != "" } // MustFrom reads the organization id or returns ErrNoOrg. func MustFrom(ctx context.Context) (string, error) { if v, ok := From(ctx); ok { return v, nil } return "", ErrNoOrg }