Context
Agent.type and Agent.services are currently served as raw enum values (AgentType, AgentServiceType), with no translation. We want them to be language-sensitive (en/de), which means they need to become "reference data with translations" — an id plus a resolvable en/de title — rather than a bare enum string.
This is the first of three issues (sdk → be → fe). be and fe work must not start until the contract here is published to npm, per the shared rule ("API changes go through the SDK contract first").
Current state
AgentType enum — src/types/api/agent.ts:8-19 (AE, GU1, GU2, GU2+, GU3, NU, ASOG, counseling-center, tandem, multiple-social-support)
AgentServiceType enum — src/types/api/agent.ts:50-61 (childcare, welfare, consultation, voluntary-support, tandem, sport, tutoring, refugee-accommodation, job-coaching, youth)
- Field usages of these enums:
AgentDetails.organizationType: AgentType (agent.ts:73), AgentDetails.services: string (agent.ts:75, free text — a third, inconsistent shape)
AgentGetList.type: AgentType (agent.ts:120)
AgentGet.serviceType: AgentServiceType[] (agent.ts:140)
AgentPatch.type: AgentType, .serviceType: AgentServiceType[], .services: AgentServiceType[] (agent.ts:153,156,163 — note serviceType and services already coexist here, pre-existing inconsistency)
ApiAgentRegisterNew.type?: AgentType, .services?: AgentServiceType[] (agent.ts:180,183)
- Existing "translated reference item" pattern already in the SDK, used today for
district:
Lang enum — src/types/core.ts:1-4 (EN, DE)
OptionTitle = Partial<{ [key in Lang]: string }> — src/types/api/common.ts:4-6
Option { id: OptionId; title: OptionTitle }, OptionById = PartialBy<Option, "title"> — src/types/api/common.ts:1-15
- Already consumed as
AgentGetList.district: OptionById — agent.ts:95
EntityTableName enum (used to key field_translation rows and generic option lists) — src/types/core.ts:54-66. Current members: NONE, ACTIVITY, AGENT, CATEGORY, COMMENT, DISTRICT, LANGUAGE, LEAD, OPPORTUNITY, SKILL, VOLUNTEER. No AGENT_TYPE / SERVICE member exists yet.
- No
CHANGELOG.md in this repo — history lives in PR titles/commit messages (feat:/fix: style) and package.json version bumps. Current version: 0.0.134.
Naming collision (needs a decision — see Open questions)
AgentType already exists as the plain string enum. If we keep the enum name and also need a "reference data" concept for the same thing, one of them needs to change name. Same issue for Service/AgentServiceType (no Service type currently exists in the SDK at all, so that one is a straightforward add).
Proposed shape (mirrors the existing district/Option pattern)
AgentGetList.type → OptionById (was AgentType)
AgentGet.serviceType / AgentPatch.services → OptionById[] (was AgentServiceType[]), reconciled into a single field name (services)
AgentDetails.organizationType → OptionById; AgentDetails.services (currently free text) → OptionById[], dropping the free-text shape
ApiAgentRegisterNew.type/.services → id (or OptionById) on write, OptionById/OptionById[] on read
- Extend
EntityTableName with AGENT_TYPE and SERVICE members so field_translation rows can reference the new tables generically, same as SKILL/DISTRICT/LANGUAGE do today
TODOs
Open questions for review
- Naming collision: rename the existing
AgentType string enum (e.g. to AgentTypeKey) and use AgentType for the new Option-shaped reference type? Or keep the enum as-is and name the reference concept something else (e.g. AgentTypeOption)? Same question doesn't apply to Service (no prior art), but consistency between the two matters.
services vs serviceType: which field name should the unified, translated many-to-many list use going forward? AgentPatch currently has both.
- Should the reference-data enums (
AgentType/AgentServiceType or their renamed equivalents) remain part of the public SDK surface at all once the values live in a DB table, or should they be treated as internal seed constants only?
Context
Agent.typeandAgent.servicesare currently served as raw enum values (AgentType,AgentServiceType), with no translation. We want them to be language-sensitive (en/de), which means they need to become "reference data with translations" — anidplus a resolvableen/detitle — rather than a bare enum string.This is the first of three issues (sdk → be → fe).
beandfework must not start until the contract here is published to npm, per the shared rule ("API changes go through the SDK contract first").Current state
AgentTypeenum —src/types/api/agent.ts:8-19(AE, GU1, GU2, GU2+, GU3, NU, ASOG, counseling-center, tandem, multiple-social-support)AgentServiceTypeenum —src/types/api/agent.ts:50-61(childcare, welfare, consultation, voluntary-support, tandem, sport, tutoring, refugee-accommodation, job-coaching, youth)AgentDetails.organizationType: AgentType(agent.ts:73),AgentDetails.services: string(agent.ts:75, free text — a third, inconsistent shape)AgentGetList.type: AgentType(agent.ts:120)AgentGet.serviceType: AgentServiceType[](agent.ts:140)AgentPatch.type: AgentType,.serviceType: AgentServiceType[],.services: AgentServiceType[](agent.ts:153,156,163— noteserviceTypeandservicesalready coexist here, pre-existing inconsistency)ApiAgentRegisterNew.type?: AgentType,.services?: AgentServiceType[](agent.ts:180,183)district:Langenum —src/types/core.ts:1-4(EN,DE)OptionTitle = Partial<{ [key in Lang]: string }>—src/types/api/common.ts:4-6Option { id: OptionId; title: OptionTitle },OptionById = PartialBy<Option, "title">—src/types/api/common.ts:1-15AgentGetList.district: OptionById—agent.ts:95EntityTableNameenum (used to keyfield_translationrows and generic option lists) —src/types/core.ts:54-66. Current members:NONE, ACTIVITY, AGENT, CATEGORY, COMMENT, DISTRICT, LANGUAGE, LEAD, OPPORTUNITY, SKILL, VOLUNTEER. NoAGENT_TYPE/SERVICEmember exists yet.CHANGELOG.mdin this repo — history lives in PR titles/commit messages (feat:/fix:style) andpackage.jsonversion bumps. Current version:0.0.134.Naming collision (needs a decision — see Open questions)
AgentTypealready exists as the plain string enum. If we keep the enum name and also need a "reference data" concept for the same thing, one of them needs to change name. Same issue forService/AgentServiceType(noServicetype currently exists in the SDK at all, so that one is a straightforward add).Proposed shape (mirrors the existing
district/Optionpattern)AgentGetList.type→OptionById(wasAgentType)AgentGet.serviceType/AgentPatch.services→OptionById[](wasAgentServiceType[]), reconciled into a single field name (services)AgentDetails.organizationType→OptionById;AgentDetails.services(currently free text) →OptionById[], dropping the free-text shapeApiAgentRegisterNew.type/.services→id(orOptionById) on write,OptionById/OptionById[]on readEntityTableNamewithAGENT_TYPEandSERVICEmembers sofield_translationrows can reference the new tables generically, same asSKILL/DISTRICT/LANGUAGEdo todayTODOs
AGENT_TYPEandSERVICEmembers toEntityTableName(src/types/core.ts:54-66)AgentType/AgentServiceTypeenums as the canonical seed key list —bewill need these values as literal seed data for the new lookup tablesAgentGetList.type,AgentGet.serviceType,AgentPatch.type/serviceType/services,AgentDetails.organizationType/services,ApiAgentRegisterNew.type/servicesto theOptionById/OptionById[]shapes aboveAgentDetails.services: string(free text) andAgentGet.serviceType: AgentServiceType[]into one consistent field — confirm withfe/bewhich name survives (servicesvsserviceType)package.jsonversion and publish to npmbe/feissues of the published version to unblock themOpen questions for review
AgentTypestring enum (e.g. toAgentTypeKey) and useAgentTypefor the newOption-shaped reference type? Or keep the enum as-is and name the reference concept something else (e.g.AgentTypeOption)? Same question doesn't apply toService(no prior art), but consistency between the two matters.servicesvsserviceType: which field name should the unified, translated many-to-many list use going forward?AgentPatchcurrently has both.AgentType/AgentServiceTypeor their renamed equivalents) remain part of the public SDK surface at all once the values live in a DB table, or should they be treated as internal seed constants only?