package server import ( "net/http" "git.lohmar.co.uk/cclohmar/NextMyDay/internal/core/routing" ) // Handler is a dispatched module function. It receives the door's resolved // RequestContext — identification and routing, never a raw path (rule of the // door). A non-nil error is logged and answered as 500. type Handler func(w http.ResponseWriter, r *http.Request, rc *RequestContext) error // Registry is the door's dispatch surface: the pure routing.Registry (so // routing.Dispatch can resolve a Resolution) plus the function lookup that // turns a resolved (module, function) into a Handler. // // SPEC-008 owns the full, discovered registry; this is the minimal in-memory // implementation that makes the door exercisable. type Registry interface { // routing.Registry is the whitelist the pure model consults. routing.Registry // Handler returns the function registered for (module, function). Handler(module, function string) (Handler, bool) // CoreHandler returns the handler for a core-owned workflow (home, access, // setup, login, enroll, …) — the reserved level-1 routes. CoreHandler(workflow string) (Handler, bool) } // MapModule is one in-memory module: its routing.Module whitelist plus its // function handlers. type MapModule struct { name string deflt string routes map[string]string actions map[string]string handlers map[string]Handler } // NewModule starts a module definition. func NewModule(name string) *MapModule { return &MapModule{ name: name, routes: make(map[string]string), actions: make(map[string]string), handlers: make(map[string]Handler), } } // Name implements routing.Module. func (m *MapModule) Name() string { return m.name } // SetDefault declares the function (and handler) for an absent/trailing PARAM3. func (m *MapModule) SetDefault(fn string, h Handler) *MapModule { m.deflt = fn if h != nil { m.handlers[fn] = h } return m } // AddRoute registers a whitelisted path-mode function. func (m *MapModule) AddRoute(name, fn string, h Handler) *MapModule { m.routes[name] = fn if h != nil { m.handlers[fn] = h } return m } // AddAction registers a whitelisted action-mode function. func (m *MapModule) AddAction(name, fn string, h Handler) *MapModule { m.actions[name] = fn if h != nil { m.handlers[fn] = h } return m } // Route implements routing.Module. func (m *MapModule) Route(function string, tail routing.Params) (string, routing.Params, bool) { if function == "" { if m.deflt == "" { return "", nil, false } return m.deflt, tail, true } if fn, ok := m.routes[function]; ok { return fn, tail, true } return "", nil, false } // Action implements routing.Module. func (m *MapModule) Action(action string) (string, bool) { fn, ok := m.actions[action] return fn, ok } // MapRegistry is the minimal in-memory Registry. type MapRegistry struct { modules map[string]*MapModule core map[string]Handler } // NewMapRegistry returns an empty registry. func NewMapRegistry() *MapRegistry { return &MapRegistry{ modules: make(map[string]*MapModule), core: make(map[string]Handler), } } // RegisterModule adds a module under PARAM2. func (r *MapRegistry) RegisterModule(m *MapModule) *MapRegistry { r.modules[m.name] = m return r } // RegisterCore adds a core-owned workflow handler (home, access, setup, login, // enroll). func (r *MapRegistry) RegisterCore(workflow string, h Handler) *MapRegistry { r.core[workflow] = h return r } // module returns the registered MapModule (nil when absent). It is the // package-internal handle a registration helper uses to EXTEND an existing // module — e.g. the SPEC-006 `auth` module gaining SPEC-007's `recover` action. func (r *MapRegistry) module(name string) *MapModule { return r.modules[name] } // Module implements routing.Registry. An unknown module is "not found" → 404. func (r *MapRegistry) Module(name string) (routing.Module, bool) { m, ok := r.modules[name] if !ok { return nil, false } return m, true } // Handler returns the function handler for (module, function). func (r *MapRegistry) Handler(module, function string) (Handler, bool) { m, ok := r.modules[module] if !ok { return nil, false } h, ok := m.handlers[function] return h, ok } // CoreHandler returns the core handler for a reserved workflow. func (r *MapRegistry) CoreHandler(workflow string) (Handler, bool) { h, ok := r.core[workflow] return h, ok } var ( _ Registry = (*MapRegistry)(nil) _ routing.Module = (*MapModule)(nil) )