// Package orgctx carries the organization a request operates on. // // Phase 2C has no authentication, so there is nothing to derive a tenant from. // Rather than defaulting org_id deep inside the SQL — where it would have to be // unpicked from fourteen repositories once auth arrives — the value is put on // the request context by one middleware and threaded explicitly through the // service and repository boundaries. // // When authentication lands, DevMiddleware is replaced by one that reads the // organization off the authenticated session. Nothing below this package // changes: every caller already takes an org id as a parameter. 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 }