Server-side persona inference
Why inference is server-side
AVX never accepts a persona identifier from the client. Persona is a privilege boundary:
the technician persona has access to parts catalog and DTC diagnostic guide content;
the fleet_driver persona has access to a different set of tabular records and operational
tools. Allowing the client to supply a persona identifier would allow any caller to claim
a higher-privilege persona, bypassing the grounding and tool restrictions the persona model
enforces.
Server-side inference closes this attack surface. The persona is derived exclusively from verified identity claims extracted by the API Gateway authorizer or the Connect contact flow Lambda — neither of which is accessible to the end user. Invalid or absent persona identifiers always default to the most-constrained persona.
Inference flow
The server-side persona inference path proceeds as follows:
-
The client or Connect channel presents a bearer token (Cognito IdToken) or a set of Connect contact attributes. No persona value is read from the request body.
-
The API Gateway Cognito authorizer validates the token and injects the decoded claims into the route Lambda’s invocation context. Claims include
sub,custom:tenantId,cognito:groups, andcustom:role. For scoped reads, additional standing claims identify who is asking:custom:customerId(owner),custom:vehicleId(driver of a specific vehicle),custom:fleetIds(manager of one or more fleets). Trust for each claim is attested per-stage in SSM — a claim’s presence in the token is necessary but not sufficient; the fail-closed authorization gate that reads Findings and Actions requires the corresponding trust flag as well. -
The route Lambda calls
infer_persona(), the authoritative mapping function inlambdas/api-assistant-chat/persona_map.py. This function reads the injected claims and applies the mapping rules:Identity signal Condition Persona assigned cognito:groupsorcustom:roleContains
platform-adminorfleet-operatorfleet_drivercustom:roleservice-advisorservice_advisorAny other value, or absent
Default fallback
fleet_driver -
The inferred
personaIdis validated against the set of known persona slugs. An unrecognized value is rejected and replaced withfleet_driver. -
The validated
personaIdis passed to the AVX runtime entry point as part of the session payload. The supervisor reads it at session initialization to select the persona’s system prompt, grounding surface, and tool factory set from the registry inagents/supervisor/persona_definitions.py.
Note
The mapping table above reflects the web-chat integration through the CMS Cognito User
Pool. Additional claims and mapping rules — for example, inferring technician from a
service-portal SSO attribute — can be added to persona_map.py without changes to the
supervisor or the persona definitions. The unit tests in tests/test_persona_map.py cover
the canonical mapping cases and must be kept up to date as new mappings are added.
Default to most-constrained
The inference rule defaults to the most-constrained persona available for the operating
context. For the web-chat integration this is fleet_driver; for a service-portal
integration it might be service_advisor. The most-constrained persona is the one with the
narrowest tool access appropriate to the channel — it ensures that an unauthenticated or
under-authenticated session cannot accidentally access grounding data or tools that belong
to a higher-trust role.
This default-to-constrained rule applies at every point where persona resolution might fail: missing claims, unrecognized role values, token validation errors that allow the session to proceed in a degraded mode, or any code path that does not explicitly infer a persona. Every persona resolution path must produce a valid, non-escalating result.