Adding a Second Audience to Frontier: The Advisor Persona, Behind a Runtime Chinese Wall
Bollwerk Frontier is a platform built for high-stakes risk teams: the groups whose decisions carry meaningful consequences when a signal is missed. Typical users sit in the second line of defence at a financial institution, but the platform serves investigators, financial-crime analysts, compliance officers, and risk managers wherever the cost of oversight error is high. Until now, every user has shared the same implicit audience — an operator cleared to see the system's surveillance output in full.
This release introduces a second audience on top of the same platform. The front-office advisor — relationship manager, private banker, corporate coverage officer — now has a surface of their own, with access rights that are narrower by construction rather than by convention.
The principle that enforces that separation is a Chinese wall: a regulatory requirement, familiar in private banking and capital-markets compliance, that mandates isolation between front-office staff and the surveillance signal generated on the customers they serve. Institutions have historically implemented Chinese walls as a procurement boundary, with entirely separate vendors and systems for each population. The advisor foundation implements the wall differently — as a runtime property of the platform itself, enforced at four independent layers whose combination makes a single defect insufficient to breach the isolation.
Overview
- Why a second persona
- The four enforcement surfaces
- Book of business as the primary authorisation key
- Client 360 for advisors
- Advisor writes: outreach, notes, recommendations
- Defaults that carry more of the wall than any single rule
- Audit and the Chinese-wall proof
- Tenant opt-in and rollout posture
- What comes next
Why a second persona
Every financial institution has two user populations working on the same customers. The front office — relationship managers, private bankers, corporate coverage officers — works with clients commercially. The second line — compliance, financial crime, risk — monitors those same clients for regulatory problems. Traditionally these two populations have used entirely separate tools, with the wall implemented as a procurement boundary: different vendors, different logins, different databases.
That separation is increasingly hard to justify. A modern customer-360 view benefits from products, positions, filings, and corporate structure being in one place. Regulators increasingly expect the institution to demonstrate a coherent view of the client. But the surveillance output the second line generates — suspicious-activity reports, screening hits, risk hypotheses, network clusters, KYC case notes — must stay invisible to the front office. Not only as individual records, but through side channels: pagination counts, search suggestions, OpenAPI schema, cache keys, error messages.
What that means for a platform serving both audiences is that the wall has to live inside the runtime. A single system has to route each request through a context that reflects the caller's role, scope every query to the caller's authorised set of relationships, project every response through a role-specific output contract, and authorise every mutation against a concrete target rather than a route. This release — the advisor foundation — implements all four.
The four enforcement surfaces
Four independent enforcement points, each doing different work. The redundancy is the whole point: projection alone leaks via pagination; query scope alone leaks via newly added fields; middleware alone leaks via forgotten routes. Only the combination holds.
%%{init: {'theme': 'default', 'themeVariables': {'fontSize': '12px'}}}%%
flowchart LR
Req([HTTP request]) --> A[A. Context resolution]
A --> B[B. Query scoping]
B --> C[C. Response projection]
C --> D{Write?}
D -->|read| Resp([Response])
D -->|write| E[D. Write authorisation]
E --> Resp
style A fill:#c9a0a0,color:#000
style B fill:#c9a0a0,color:#000
style C fill:#c9a0a0,color:#000
style E fill:#c9a0a0,color:#000
A. Context resolution. Every request into the advisor route tree passes through a pre-handler that reads the caller's identity, loads their active book of business as of the request timestamp, and attaches an authorisation context to the request. The context carries tenant, user, role, a request identifier, and — for small enough books — the full set of in-book relationship and party identifiers. Above a configurable size threshold, the identifier sets are skipped in favour of indexed subquery joins against the assignment table. Either way, the cost of context resolution is bounded; it does not grow with the size of the caller's book.
B. Query scoping. Every read composes a scope predicate that restricts rows to the caller's tenant and, for advisors, to the caller's book. For forbidden entities — screening hits, risk hypotheses, investigations, suspicious-activity cases, alerts, the internal-controls surface, and others — that scope resolves to an explicit false predicate that yields zero rows. Not "zero after pagination", and not "zero after projection". Zero rows, before pagination counts, search predicates, ordering, and cache keys. Integration tests assert the correct shape of that predicate for every allowed entity.
C. Response projection. After a query returns, rows pass through a role-specific projector that maps them to an explicit advisor DTO (data-transfer object — the shape the API returns to the client). Advisor DTOs are distinct types, not subset copies of the compliance DTOs. The distinction matters: a subset copy leaks silently when a new surveillance-derived field is added to the base type, because the subset defines its allowlist by omission. A distinct type fails the build when a new field is needed, forcing a conscious decision about whether the advisor persona may see it. A static analysis check walks every advisor DTO and fails the build if any name on the forbidden-field list appears in its projection.
D. Write authorisation. Before every mutation, an authorisation check runs against the concrete target object rather than the route. It verifies tenant, book membership at request time, and — for update and delete — author ownership. Mutations execute inside a database transaction so the book-membership check and the write cannot be separated by a concurrent assignment change. A typed denial error maps in the API error handler to an HTTP status code: 403 on a cross-tenant attempt, 404 on an out-of-book write or a forbidden entity.
Book of business as the primary authorisation key
The scope is the relationship, not the party. A single person or legal entity can hold multiple relationships with an institution: a private-banking relationship covered by one advisor while a corporate relationship on the same party is covered by another. Each advisor sees their own relationship on the shared party and nothing of the other's. Party visibility is derived from relationship visibility — a party is visible if and only if at least one active in-book relationship refers to that party.
Assignments are stored with explicit validity windows, status, and reason. Active-ness is defined once and reused everywhere a request context is built, so the definition of "active" does not drift between call sites. Terminated and superseded assignments are never active, regardless of dates.
Database-level constraints bound the state space: each relationship has at most one open-ended primary advisor per tenant; no two active-primary windows on the same relationship may overlap; only primary assignments can be open-ended; and composite tenant-keyed foreign keys reject any row that would pair one tenant's relationship with another tenant's user. Malformed cross-tenant rows are prevented at the database level, not only at the application layer.
Reassignment is atomic. Superseding one assignment closes the previous row and inserts the new row in a single transaction; at no instant does a relationship have zero primaries or two. An administrative surface exposes create, supersede, and terminate operations to authorised operators (admin or compliance officer role), and future-dated mutations are rejected so that no one can engineer a book-ownership gap. Subscribers on the advisor surface receive a refresh event on every assignment change, so UI caches invalidate immediately.
Client 360 for advisors
The Client 360 read surface returns a single composite view of an in-book party: the party itself, its in-book relationships, holdings on those relationships, exposure computed from in-book holdings and market quotes, and the advisor's own outreach log, notes, and product recommendations. Each component is scoped and projected.
Market data is projected, not passed through. Market tables carry fields that are surveillance-adjacent by design — AI summaries of filings, extracted forensic data, risk signals, verification metadata. Those fields are valuable to a compliance operator and off-limits to an advisor. Every market table therefore has its own explicit advisor-side projection that enumerates the safe fields by construction, so a forbidden field cannot appear in the output because it does not exist on the output type. Where a market table lacks a direct tenant column, the query scopes through the tenant-carrying parent rather than relying on an implicit one.
Regulatory filings on in-book parties are retrievable. A dedicated endpoint returns a short-lived signed download URL to the file in object storage, issued only after the in-book check passes. Raw storage coordinates — bucket names, object keys, source URLs — never leave the server. Unauthorised filing identifiers resolve to 404.
Advisor writes: outreach, notes, recommendations
Three write surfaces capture the artefacts of an active client relationship:
- Outreach log — recorded interactions with the client: channel, topic, outcome, per-interaction summary.
- Notes — free-form advisor annotations, with a twenty-four-hour delete window so an accidental note can be removed but a retrospective audit cleanup cannot.
- Product recommendations — products recommended to the client, with rationale, client response, and timestamp.
None of these are surveillance records. They are authored by the advisor and visible to other in-book advisors on the same relationship. Each write route runs through the four-surface stack described above.
Every write wraps its mutation in a database transaction that re-reads book membership inside the transaction, closing any gap between authorisation and commit. Row-level security, enforced by the database on the advisor write tables, means an application-layer defect cannot produce a cross-tenant write even transiently. At service boot the platform asserts that the trigger is in place and fails fast if it is not; the system is designed to refuse to start rather than come up in a half-protected state.
Defaults that carry more of the wall than any single rule
A small number of defaults, applied consistently, end up doing more work than the individual rules sitting behind them.
404 over 403. An advisor caller receives the same 404 body whether the requested resource is out of book, a forbidden entity, or a URL that does not exist. A 403 would confirm the resource exists and is merely off-limits, which leaks existence to an enumeration attack. A byte-equal 404 body across forbidden, unknown, and unauthenticated responses is enforced by a test sweep rather than left to convention.
Deny over absence. Forbidden entities are not merely missing from the rule registry. They are registered with an explicit deny rule, so the set is auditable and enumerable. A continuous-integration invariant fails the build unless every database table is explicitly classified — either with an advisor-safe projection or with an explicit deny. A new table breaks the build until classified, which is precisely the intended behaviour: the person adding the table decides.
Explicit projections. Every allowed entity has an explicit advisor-side projection that enumerates the fields an advisor may see. No allowed entity reuses a subset of the compliance projection. The static analysis check mentioned earlier enforces the contract on the type itself rather than at the call site, which means the check catches surveillance leakage as soon as the type is written — not when someone remembers to guard a route.
Role-aware API documentation. The OpenAPI schema is filtered by caller role. Authenticated advisors see the advisor tree. Unauthenticated callers see no advisor surface at all. Compliance operators see everything except the advisor-internal surface.
Audit and the Chinese-wall proof
Every advisor action, read or write, emits an audit row. Advisor events map onto canonical fields in the existing audit log so that each event carries an unambiguous role marker, a correlation identifier, and an outcome flag on explicit denials.
Two SQL queries ship with the platform that a compliance officer can run over any time window to prove the wall held. The first enumerates every advisor request in the window and asserts that none touched a forbidden entity. The second, scoped to a specific party, confirms that no advisor request in the window read a surveillance record on that party. The queries are executable, version-controlled, and shipped with the platform, so the wall is not only enforced — it is provable on demand.
Tenant opt-in and rollout posture
The advisor persona is gated by a tenant-level feature flag that defaults to off. When the flag is off, the entire advisor route tree returns 404 — indistinguishable from an unknown URL, and absent from the OpenAPI schema for that tenant.
Administrative staff enable the flag per tenant via a dedicated admin route that requires an administrative role and emits an audit event on every flip. Pilot institutions opt in explicitly; the default posture is that no tenant carries the advisor surface until enabling it is a conscious decision.
The authorisation layer has a bounded-cost fast path and a scalable slow path. Small books populate in-memory identifier sets on the request context, giving constant-time membership checks. Larger books fall back to indexed subquery joins against the assignment table, evaluated per query. A short-lived cache on the book load, invalidated on every assignment mutation, bounds the cost of context resolution under sustained load.
What comes next
The advisor persona foundation is the first of seven sub-projects in the broader advisor programme. The ones ahead, each with its own design spec: an audit UI and compliance query tools built on the Chinese-wall proof queries; continuous regression tests for surveillance isolation; a policy-administration UI; and workflow extensions for triage, suitability, and appropriateness.
The foundation's write surface is deliberately limited to outreach, notes, and recommendations — the records an advisor generates in the normal course of a client relationship. Suitability workflows, appropriateness tests, and trade-execution integration come in later phases, built on the same four-surface pattern established here.
If your institution is interested in the pilot programme, write to hello@bollwerk.ai.