The problem this solves

Not every entity in a group is wholly owned. Local foreign-ownership rules in several retail markets โ€” Mexico, Saudi Arabia, and others โ€” require a local partner to hold a minority stake before a foreign retailer can operate there at all, and some international expansion happens through minority equity stakes rather than acquisitions. Consolidating these entities correctly means answering two questions for each one: does the parent control it, and if so, how much of its results belong to outside shareholders rather than the parent?

Get the method wrong โ€” full-consolidate an entity that should be equity-method, or forget to carve out NCI on one that should be full-consolidated โ€” and the group's reported revenue, assets, and net income are all misstated, not by a rounding amount but by the entire uncontrolled or unconsolidated entity.

Audience

Consolidation accountants and controllers who set the group's ownership structure and consolidation method by entity. Corporate development and M&A teams evaluating new market entry structures (wholly owned vs joint venture vs minority stake). FP&A teams who need to understand why "consolidated net income" is smaller than the sum of every entity's reported net income.

Three entities, three ownership structures

EntityOwnershipMethodWhy
NLQ query: "Show NCI for FY26" or "Equity method entities actual" โ€” DeepSeek resolves year and scenario; all three non-wholly-owned entities always render together
Mexico City70%Full + NCILocal-partner requirement under Mexican retail foreign-ownership rules
Bogotรก40%Equity methodStrategic equity stake โ€” significant influence, not control
Riyadh65%Full + NCISaudi retail foreign-ownership rules require a local JV partner

Every other entity in the cube defaults to 100% ownership, Full consolidation, and zero NCI.

Parent share, NCI share, and one equity-method line

  • Ownership cards: one per non-wholly-owned entity, showing the ownership %, the method badge, and the plain-language reason for that structure
  • Stacked chart: for the two Full-consolidated entities, Parent Share vs NCI Share of net income, side by side
  • Consolidation detail table: subsidiary revenue and net income (100%, before any ownership adjustment) next to what actually lands in the consolidated result

The last step of the consolidation sequence

Ownership and NCI apply after Currency Translation (so the math runs on USD-denominated results) and after Intercompany Eliminations (so IC transactions with the JV/investee entities are already netted out) โ€” the third and final step this module's three use cases walk through in sequence.

Recommended integration points

  • New market entry: before signing a JV agreement, model both the 70%-Full and a hypothetical 40%-Equity structure to see the NCI/equity-pickup impact on consolidated net income before the deal terms are final
  • Board reporting: distinguishing "Net Income Attributable to Parent" (what shareholders actually care about) from "Consolidated Net Income" (which still includes 100% of Full-consolidated subsidiaries, NCI and all)
  • Local-partner renegotiation: if Mexico City's local-partner stake changes from 30% to 20%, this is exactly the calculation that needs to re-run

The numbers

44
Total entities
3
Non-wholly-owned
2
Full + NCI
1
Equity method
$0.0002
Cost per NLQ query
40%
Lowest ownership stake

The honest checklist

  • โœ“Any entity in your group is less than 100% owned โ€” a JV, a strategic stake, or a local-partner requirement
  • โœ“You need to distinguish "consolidated net income" from "net income attributable to the parent" in board or investor reporting
  • โœ“You're modeling a new market-entry structure and need to see the consolidation impact of different ownership percentages before signing
  • โœ—Every entity in your group is wholly owned โ€” there is no NCI or equity method to calculate
  • โœ—You need the Proportional or Cost consolidation methods modeled explicitly โ€” this demo implements Full and Equity only, the two methods this retailer's three minority structures actually use

Try it now

The live demo computes NCI and equity-pickup for all three entities in real time.

Launch Ownership & NCI โ†’ Start a Lab engagement

Things to try

  • Type "Show NCI for FY26" into the NLQ bar and compare Mexico City (70% Full) against Bogotรก (40% Equity) โ€” notice Bogotรก contributes only one small line to consolidated income, while Mexico City contributes its full revenue and assets plus an NCI carve-out
  • Switch scenario to Actual and watch every NCI and parent-share figure recompute from the underlying entity P&L
HOW WE BUILT IT

Control is a legal test, not an ownership percentage

The accounting question is not "how much of this entity do we own" โ€” it's "do we control it." Ownership above 50% is a strong presumption of control and typically drives Full consolidation. Ownership in the 20โ€“50% range typically indicates significant influence without control, which drives the Equity method. But these are presumptions, not mechanical thresholds โ€” a 45% stake with contractual board control still consolidates fully, and a 55% stake subject to substantive minority protective rights might not. This demo models the common case (ownership percentage determines the method) because that is the right level of fidelity for illustrating the consolidation math; a production system's method assignment is a judgment call documented per entity, not a formula.

Ownership lookup โ†’ method branch โ†’ NCI/equity math

OWNERSHIP[entityId] lookup — defaults to 100% / Full / "Wholly owned"
1
computeConsolidation()
entityId, year, scenario
  • Branches on consolidation method — see below
Equity Method
equityInEarnings = subsidiaryNI × ownership%
  • Nothing else consolidates
Full Consolidation
consolidatedRevenue = consolidatedNI = 100%
  • nciNI = subsidiaryNI × (1 − ownership%)
  • nciEquity = totalEquity × (1 − ownership%)
  • parentNI = subsidiaryNI − nciNI
2
Renderer
ownership.html
  • Ownership cards
  • Stacked Parent/NCI chart
  • Detail table

App UI โ€” Component breakdown

ComponentBehaviour
Ownership cardsOne per non-wholly-owned entity โ€” name, method badge, plain-language rationale, and the key numbers for that method
KPI rowCount of non-wholly-owned entities, split by method, plus total NCI net income across the group
Stacked chartParent Share vs NCI Share, Full-consolidated entities only โ€” Equity-method entities have no NCI to show, so they're correctly excluded from this chart
Detail tableSubsidiary-level (100%) revenue/NI next to the actual consolidated contribution, making the "before ownership adjustment" and "after" numbers directly comparable

Full vs Equity โ€” what actually differs

Full ConsolidationEquity Method
Revenue consolidated100% โ€” line by line0% โ€” no line-item consolidation
Assets/Liabilities consolidated100% โ€” line by line0% โ€” investment carried as a single BS asset
Net income impact100% flows to consolidated NI, then NCI carves out the minority shareOnly "Equity in earnings of investee" = ownership% ร— investee NI
Typical ownership range>50%, control20โ€“50%, significant influence without control

The demo deliberately shows both methods side by side on entities with genuinely different structures (Mexico City and Riyadh are both foreign-ownership-driven JVs at Full+NCI; Bogotรก is a strategic minority stake at Equity) so the contrast is visible in the same screen rather than described in the abstract.

Why the two numbers can diverge

Ownership percentage is an economic-interest measure โ€” how much of the entity's value belongs to the parent. Consolidation percentage (or "control") is a legal/governance measure โ€” whether the parent's financial statements should include the entity's results at all, and at what proportion. In the common case these move together (own more than half, you control it), which is why this demo's OWNERSHIP table uses ownership percentage as the practical driver of method. But the two can separate: contractual voting rights, board composition, and protective rights for minority shareholders can all shift where control actually sits independent of the raw ownership percentage.

This matters operationally because the method decision, once made, has to be revisited whenever the governance arrangement changes โ€” a JV agreement renegotiation, a shareholder rights amendment โ€” not just when the ownership percentage itself changes.

Two NCI lines, not one

// Full consolidation NCI โ€” computed on two different bases
nciNI     = subsidiaryNetIncome ร— (1 - ownershipPct)   // income statement
nciEquity = subsidiaryTotalEquity ร— (1 - ownershipPct) // balance sheet

nciNI is the minority shareholders' share of this period's net income โ€” it appears below consolidated net income, splitting it into "Net Income Attributable to Parent" and "Net Income Attributable to Non-Controlling Interests." nciEquity is the minority shareholders' share of the subsidiary's cumulative equity โ€” it appears as a separate line within total equity on the consolidated balance sheet, distinct from the parent's own retained earnings and common stock. These are two different bases (one period's flow, one point-in-time stock) computed the same way, and conflating them โ€” showing only one NCI number instead of both โ€” is a common simplification error worth calling out explicitly.

Cost per query

ComponentDetailCost
LLM input tokens~600 tokens (smallest schema of the nine โ€” just year/scenario)$0.000084
LLM output tokens~40 tokens$0.0000112
Ownership/NCI calculationClient-side arithmetic once the query resolves$0
Total per query~$0.0001
With 2ร— safety margin~$0.0002

Ownership has the cheapest query of the nine use cases โ€” there's no entity to resolve, only year and scenario, since all three non-wholly-owned entities always render together. The value is in modeling Full-vs-Equity consolidation correctly, not in retrieval, and the LLM's job here is correspondingly small.

Cost model โ€” At-scale projections

LLM cost is flat per query at roughly $0.0002, regardless of how many non-wholly-owned entities the group has โ€” the query only resolves year and scenario, and every non-wholly-owned entity renders in the same response. NCI and equity-method calculation itself scales linearly with the number of non-wholly-owned entities, which even for a large group is a small fraction of the total entity count โ€” trivial client-side compute at any realistic scale. The real cost driver in production is maintaining the ownership table itself as stakes change through renegotiation, dilution, or buyout.

Key files

FileRole
epm-nlq-src/assets/epm-fccs-data.jsOWNERSHIP, getOwnership(), computeConsolidation()
epm-nlq-src/pages/ownership.htmlUI: NLQ bar, ownership cards, stacked Parent/NCI chart, consolidation detail table
epm-nlq-src/assets/epm-data.jsShared ENTITIES and genIS() โ€” subsidiary revenue and net income come straight from the FP&A module's existing P&L generator
functions/api/nlq-query.jsShared NLQ endpoint; Ownership uses useCase: "ownership" โ€” year/scenario only, the smallest schema of the nine

Why the same three entities appear in Eliminations too

Mexico City, Bogotรก, and Riyadh are the borrowers in the Intercompany Loan Interest transaction type in UC8 โ€” Corporate HQ's formation funding for exactly these three minority structures. That's deliberate cross-linking, not coincidence: a real consolidation process treats ownership structure, intercompany funding, and translation as three views of the same underlying entity relationships, and the demo data is built to make that connection visible rather than modeling each use case with an unrelated cast of entities.

Tech stack โ€” Every tool in this build

LayerToolWhy
Data layerepm-fccs-data.js (vanilla JS)Deterministic consolidation math โ€” the LLM only resolves year/scenario
LLMDeepSeek V3Shared NLQ endpoint; smallest schema of the nine use cases โ€” year/scenario only
ChartsChart.js 4.xShared with Analytics UC4, Capital UC6, and Translation UC7; stacked bar for Parent vs NCI share
Edge hostingCloudflare PagesStatic file, no server compute needed for this use case
BuildEleventy v3.1.5Copies epm-nlq-src/pages/ and epm-nlq-src/assets/ to _site/ verbatim

Known attack surfaces

ThreatMitigation in this build
Wrong method applied to an entityMethod is stored explicitly per entity in OWNERSHIP, not derived automatically from a threshold โ€” a deliberate choice documented in this kit (see "Ownership vs Control") so a judgment call is never silently overridden by a formula
NCI computed on the wrong basisnciNI and nciEquity are two explicit, separately-computed fields โ€” there is no single "NCI" number that conflates a period flow with a point-in-time balance
Stale ownership percentageDemo data is static by design; production requires the ownership table to be updated whenever a stake changes, ideally triggering a re-run of this calculation as part of the change process

Guardrails โ€” What prevents bad consolidation math

  • Method branch is explicit, not inferred at render time: computeConsolidation() checks the method once and returns a completely different result shape for Equity vs Full โ€” the two paths can't be accidentally blended
  • Parent share reconciles to subsidiary NI exactly: parentNI + nciNI === subsidiaryNI by construction for Full-consolidated entities โ€” no rounding drift between the two shares
  • Default is always 100% / Full / wholly owned: any entity not explicitly listed in OWNERSHIP is guaranteed to consolidate at 100% with zero NCI, so a missing configuration entry fails safe rather than silently under-consolidating

Who is asking, and what are they allowed to see?

The demo answers neither question — it has a cookie gate and no notion of a user. In production these are the two questions everything else rests on, and they have different answers: authentication is who you are, authorization is what you may see. Corporate SSO settles the first. Only Oracle EPM Cloud can settle the second, and the single most important rule in this section is that this application must never become the place where that decision is made.

The rule that governs every choice below: a user must see exactly what they would see by logging into Oracle EPM Cloud directly — no more, and no less. If this tool can surface a number the user could not retrieve themselves, it has become a privilege-escalation path, and it will be found in the first access review.

9.1 · The identity chain, end to end

Finance user opens the tool in a browser — no local account, no password held here
1
Corporate identity provider
Entra ID · Okta · OCI IAM
OIDC Authorization Code + PKCE  (or SAML 2.0)
  • MFA and Conditional Access are enforced here — device compliance, location, risk signals
  • Returns an ID token (who the user is) and an access token (what they may call)
  • Group membership arrives as a claim; the application never handles a password
2
Application session
validate, never trust
  • Verify signature, issuer, audience and expiry against the IdP’s published keys
  • Read the group claims — there is no local user table and no local role table
  • Short-lived access token with refresh-token rotation; session timeout set to the data classification
Pattern A — identity propagation
OAuth 2.0 token exchange (on-behalf-of)
  • The API is called as the user
  • EPM enforces its own security natively
  • Audit trail names the real user
  • Preferred where the API supports it
Pattern B — service account + filtering
one read-only integration account
  • The application becomes the enforcement point
  • Entitlements fetched separately, applied in one audited place
  • Simpler and cacheable — and a filtering bug is a data breach
3
EPM identity domain
roles + dimension security
  • Roles: Service Administrator, Power User, User, Viewer — assigned to groups, never to individuals
  • Data level: FCCS data access by Entity, plus restricted access to the ownership management screens themselves
  • Group → role mapping lives in the platform, not in this application
Result, filtered to this user
ownership.html
  • The user sees exactly what they would see logging into the source system directly — no more
  • Every query logged against the real end user, never a shared account

9.2 · Federating the corporate identity provider

Oracle EPM Cloud does not replace your directory — it trusts it. The EPM Cloud identity domain is federated with the corporate IdP so authentication happens where it already happens, under policies security has already written.

Identity providerProtocolNotes
Microsoft Entra ID (formerly Azure AD)SAML 2.0 or OIDCThe common case. Conditional Access, MFA and device compliance are enforced at Entra and inherited automatically. On-premises Active Directory federates through Entra Connect rather than being integrated directly.
OktaSAML 2.0 or OIDCSame pattern; Okta groups drive EPM roles through SCIM provisioning.
OCI IAM (identity domains)NativeAlready present with Oracle EPM Cloud. Can be the primary IdP for a smaller estate, or a federated spoke of Entra/Okta for a larger one.
AD FSSAML 2.0Still seen where the estate is not yet cloud-first. Works, but you inherit the on-premises availability of the token service — if AD FS is down, nobody logs in.

For the browser application itself, use OIDC Authorization Code flow with PKCE. Not the implicit flow, which is deprecated and leaks tokens through the URL, and never a resource-owner password grant — a finance tool should not be capable of handling a password at all.

9.3 · From group membership to EPM roles

Roles are granted to groups, never to individuals, and the groups come from the directory. That one discipline is what makes joiner/mover/leaver work without anyone having to remember this application exists.

Entra ID group                    โ†’  EPM role / entitlement
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
FIN-EPM-Analysts                  โ†’  Planning User
FIN-EPM-Controllers-EMEA          โ†’  Power User + EMEA data scope
FIN-EPM-Admins                    โ†’  Service Administrator
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Provisioned by SCIM. Remove the user from the group and the
entitlement disappears on the next sync โ€” including here.

For this use case the relevant native entitlement is: FCCS User; Manage Ownership is typically restricted to a small consolidation group.

9.4 · The architectural decision: who enforces?

This is the choice that determines whether the deployment is defensible. Both patterns appear in the diagram above; the difference is where the security boundary actually sits.

Pattern A — identity propagationPattern B — service account + filtering
HowThe user’s token is exchanged (OAuth 2.0 on-behalf-of) for one scoped to the EPM API; calls are made as the userA single read-only integration account calls the API; the application filters the results
Enforcement pointOracle EPM CloudThis application
Audit trail showsThe real end userThe service account — you must log the real user separately
Failure modeToken plumbing is more complex; per-user rate limits applyA filtering bug is a data breach, and the entitlement copy drifts from reality
VerdictPrefer this wherever the API supports user-token authenticationAcceptable with discipline: narrowest possible service account, filtering centralised in one tested place, real user in every log line

The shortcut to refuse. Pattern B built with a Service Administrator account and no filtering at all is the most common way this gets delivered, because it works perfectly in UAT — testers are usually over-entitled, so nobody notices that everyone can see everything. It fails at the first access review, and by then it is in production with real users depending on it.

9.5 · Data-level security is the part that matters

Role membership decides whether a user can open the application. It does not decide which rows they get back, and confusing the two is the most expensive mistake available here.

  • For this use case: FCCS data access by Entity, plus restricted access to the ownership management screens themselves.
  • Apply it before aggregation, not after. Filtering a total that has already been computed across entities the user cannot see still leaks the total.
  • The NLQ layer needs its own check. Layer 4 already validates that the resolved point of view uses approved members; production adds a second test — that the resolved POV sits inside this user’s scope — and it runs before the data call, not after. A natural-language interface is very good at asking for things politely; the authorization check must not care how the question was phrased.
  • Fail closed. If entitlements cannot be resolved, return nothing and say so. An empty result is a support ticket; a permissive default is an incident.

9.6 · Provisioning, sessions and the leaver problem

  • SCIM provisioning from Entra or Okta into the EPM Cloud identity domain (OCI IAM, formerly IDCS), covering joiner, mover and leaver. The mover is the case people forget — somebody changing region should lose the old scope, not accumulate both.
  • No local user store. If this application keeps its own copy of who may do what, a leaver keeps access until somebody remembers to update it. Nobody ever does.
  • Short-lived access tokens with refresh-token rotation; align session timeout with the data classification rather than with convenience.
  • MFA and Conditional Access at the IdP — not reimplemented here. Device compliance and location policy come free with federation.
  • Quarterly recertification of both the groups that grant access and the service account’s own entitlements, evidenced and signed.
  • Break-glass access is a named, monitored, time-boxed account — never a shared credential in a password manager.

9.7 · What this means for Ownership & NCI

ConcernAnswer for this use case
Native entitlement requiredFCCS User; Manage Ownership is typically restricted to a small consolidation group
Data-level controlFCCS data access by Entity, plus restricted access to the ownership management screens themselves
Use-case-specific sensitivityOwnership percentages and consolidation methods are board-level and deal-sensitive — a change to a JV stake is often price-sensitive information before it is announced. Keep the ownership table visible to consolidation and leadership only, and log every view.

9.8 · Security configuration checklist

  • ✓Oracle EPM Cloud federated with the corporate IdP over SAML 2.0 or OIDC; the cookie gate removed entirely
  • ✓Browser app uses OIDC Authorization Code + PKCE — no implicit flow, no password grant
  • ✓MFA and Conditional Access enforced at the IdP, not reimplemented in the application
  • ✓Roles granted to directory groups, never to individuals; SCIM covers joiner, mover and leaver
  • ✓Enforcement pattern chosen deliberately — Pattern A where the API supports it, or Pattern B with filtering centralised and tested
  • ✓Data-level security applied before aggregation, and the resolved POV checked against the user’s scope before the data call
  • ✓No local user table and no local role table anywhere in the application
  • ✓Every query logged against the real end user, even when a service account makes the call
  • ✓Authorization failures fail closed and are logged as security events rather than swallowed
  • ✓Quarterly recertification of access groups and of the service account’s own entitlements
Talk through your identity model → Back to the demo

From demo to a governed enterprise deployment

Everything above runs on synthetic data, a public LLM API key, a cookie gate, and no audit trail — deliberately, so the mechanics are inspectable. Taking Ownership & NCI to production is not a rewrite; the 4-layer pipeline and the data-layer contract survive intact. It is a controlled-change program across six workstreams: architecture, LLM platform, security, SOX/audit, environment promotion, and operations. This section is the checklist we run with clients.

The one rule that matters most for this use case: in the demo the browser computes the result; in production Oracle computes and this layer retrieves and explains. Never ship a second calculation engine that can disagree with the system of record — the moment two numbers exist, the audit question becomes “which one is right,” and the answer must always be the EPM module.

10.1 · Production reference architecture

Finance user · corporate SSO (OIDC/SAML + MFA) · EPM role claims
1
Edge / API Gateway
WAF · rate limit · identity
  • Terminates SSO, validates the session, attaches the user’s EPM groups to the request
  • Rate limits per user, blocks anonymous access, scrubs PII patterns before anything reaches the orchestrator
2
NLQ Orchestrator
the 4-layer pipeline, hardened
L1 guardrails → L2 grounding → L3 LLM adapter → L4 eval + fallback
  • L2 grounding reads dimension metadata from EPM on a schedule — not a hardcoded schema
  • Only the schema + user query go to the model; financial values never leave the data layer
  • L4 rejects anything outside the approved member lists and falls back to the deterministic parser
Oracle OCI Generative AI
same tenancy as EPM Cloud
  • Data stays inside the OCI boundary
  • Natural fit when EPM is already in OCI
Azure OpenAI / AWS Bedrock / Vertex AI
private endpoint, zero retention
  • Use the hyperscaler the org already governs
  • Enterprise DPA, no training on prompts
Self-hosted open weights
VPC / air-gapped
  • For regulated or sovereign data
  • Highest control, highest run cost
3
EPM Data Layer
Oracle EPM REST API
  • Oracle FCCS Manage Ownership — ownership %, consolidation method, and NCI as computed by FCCS consolidation via REST
  • Least-privilege service account (read-only role, one app, one pod) with the token in a vault and rotated
  • Results filtered to the requesting user’s EPM security before rendering
4
Audit & Observability
append-only
  • Every query logged: user, timestamp, raw query, parsed intent JSON, model + prompt version, POV returned, latency, cost
  • Exported to the SIEM; retained per the SOX evidence schedule
  • Dashboards for fallback rate, eval pass rate, guardrail hits, p95 latency, spend
Rendered result + evidence trail
ownership.html
  • The parsed JSON is shown to the user as the explanation (“AI: entity · year · scenario — 93% confident”) — the same line the demo prints today
  • Every number on screen traces to an EPM cell intersection an auditor can reproduce

10.2 · Choosing the LLM platform

The demo’s DeepSeek call is a placeholder for a single adapter, callLLM(system, user), behind Layer 3. Swapping the provider changes one function and zero business logic. Pick the platform the organisation already governs — the security and procurement review is the long pole, not the integration.

OptionChoose whenData posture
Oracle OCI Generative AI (Cohere Command, Llama)EPM Cloud already lives in OCI; you want one cloud boundary and one contractPrompts stay in the OCI tenancy; no training on customer data; dedicated AI clusters available for isolation
Azure OpenAI ServiceMicrosoft-first finance estate (Entra ID, Purview, Sentinel already in place)Private endpoint, regional deployment, zero-retention by default under the enterprise agreement
AWS Bedrock (Claude, Titan) / Google Vertex AI (Gemini)The org’s landing zone is AWS or GCP; VPC endpoints and IAM already auditedVPC/PSC private access, no data used for training, CloudTrail/Cloud Audit Logs integration
Direct enterprise API (Anthropic, OpenAI)Fastest model access; acceptable when a zero-data-retention agreement and DPA are signedZDR endpoint, SSO-managed keys, SOC 2 report on file
Self-hosted open weights (Llama, Mistral, Qwen via vLLM)Sovereign or air-gapped requirements; regulated data classification forbids any external inferenceFull control; you own patching, eval, and capacity — budget for an MLOps owner

Put a model gateway in front of whichever you choose (Azure API Management, OCI API Gateway, Kong AI Gateway, LiteLLM, or Portkey): it owns key custody, per-team spend caps, routing and fallback between models, prompt/response logging, and lets you retire a deprecated model without touching the application.

10.3 · Security controls

ControlImplementation
Identity & accessCovered in full in section 09 — corporate SSO, group-to-role mapping, and the decision about who enforces data-level security. Listed here because it is a production gate, not because it is optional.
Service accountOne read-only EPM service account per application per pod, least-privilege role, no interactive login, credential in a vault (OCI Vault, Azure Key Vault, HashiCorp Vault), rotated on a schedule and on staff change.
Secrets & configNo secrets in code or build artifacts; environment-specific config injected at deploy; .dev.vars-style files never leave a developer machine.
NetworkPrivate endpoints to the LLM provider and to EPM where the platform supports them; egress allow-list so the orchestrator can reach exactly two hosts; TLS 1.2+ everywhere.
Prompt-injection & input guardrailsLayer 1 (already in the demo) blocks instruction-override patterns, enforces length and scope; extend with a classifier on the gateway and log every rejection.
Output guardrailsLayer 4 (already in the demo) validates every returned member against the approved lists and strips unexpected keys; production adds a policy check that the resolved POV is inside the user’s security scope before the data call.
Data minimisationPrompts contain metadata and the user’s query only. No cell values, no employee names, no free-text comments from EPM. Logged prompts are classified and retained accordingly.
EncryptionIn transit (TLS) and at rest (provider-managed KMS); audit logs on immutable storage with customer-managed keys where policy requires.

10.4 · SOX, audit, and model-risk controls

A read-only NLQ layer does not change a financial-reporting control, but it is an interface to a SOX-relevant system and lands squarely in ITGC scope. Treat prompts, schemas, and eval sets as code — that single decision satisfies most of what an auditor will ask for.

RequirementHow it is satisfied
Complete, immutable audit trailAppend-only log of user, timestamp, raw query, parsed JSON, model and prompt version hash, POV returned, and row count — WORM storage, retained for the evidence period (typically 7 years), exported to the SIEM.
Change managementPrompt templates, few-shot examples, approved-member schema, and code are version-controlled; every change follows ticket → peer review → test evidence → CAB approval → deploy. A prompt edit is a code change.
Segregation of dutiesDevelopers cannot deploy to production; the service-account owner is not a developer; production secrets are held by platform operations.
Access recertificationQuarterly review of who can use the tool and of the service account’s EPM roles, evidenced and signed.
Testing evidenceA golden-query regression suite (the few-shot examples plus a larger labelled set) runs in CI before every release; pass rate and diffs are archived as release evidence.
Model risk managementAn inventory entry (intended use, limitations, owner, validation date) in the model-risk register — the SR 11-7 pattern for financial services; periodic re-validation when the model or prompt changes.
Reproducibility & lineageEvery displayed number traces to an EPM POV and a consolidation/calculation timestamp; an auditor can re-query the same intersection in EPM and match it.
ExplainabilityThe parsed intent JSON is the explanation and is shown to the user on every response — no hidden reasoning between the query and the data call.

10.5 · Dev → Test → Prod promotion

EnvironmentEPM targetDataGate to leave
DevEPM Test pod (developer slice)Synthetic or maskedUnit tests on the data layer; lint; eval suite ≥ threshold against the Test LLM deployment
Test / UATEPM Test pod (full refresh)Masked copy of productionBusiness UAT sign-off on the golden queries; security scan; performance run (p95 latency, fallback rate)
ProdEPM Production podLiveChange ticket approved; deploy in window; smoke test; hypercare with rollback ready
  • Promoted artifacts: application build, prompt templates (versioned), approved-member schema snapshot, eval set, infrastructure config (IaC) — all from the same Git tag.
  • Pipeline: branch → PR review → CI (tests + evals) → deploy to Test → UAT sign-off → CAB → deploy to Prod → smoke test. Hosting can stay on Cloudflare Pages/Workers or move to OCI Functions + API Gateway or the org’s standard platform — the code does not care.
  • Configuration: per-environment secrets and endpoints injected at deploy; the same build runs in every environment.
  • Metadata sync: a scheduled job refreshes dimension metadata into Layer 2 grounding with change detection, so a new entity or account appears in the approved lists without a code release.
  • Rollback: previous build and previous prompt version retained; rollback is a redeploy, and because prompts are versioned it also reverts a prompt regression.

10.6 · Operating it

  • SLOs: p95 latency, availability of the read path (the deterministic fallback keeps it alive when the LLM is down — already built), fallback rate as a quality signal, eval pass rate per release.
  • Cost governance: per-user and per-team token budgets at the gateway; alert on anomalies; the unit-cost model earlier in this kit is the baseline.
  • Model lifecycle: providers retire models on a schedule — re-run the eval suite on the successor before switching, and record the switch as a change.
  • Incident runbook: LLM outage → fallback parser; EPM API outage → cached metadata with a stale banner; guardrail spike → review logs for injection attempts.

10.7 · What changes for Ownership & NCI

ConcernProduction answer
System of recordOracle FCCS Manage Ownership — ownership %, consolidation method, and NCI as computed by FCCS consolidation via REST
Read/write postureRead-only. Ownership and method changes are controlled changes made in FCCS with approval.
Use-case-specific controlConsolidation method is a documented judgment, not a threshold — display the method FCCS holds and the effective date; never infer it from the percentage in production.

10.8 · Production readiness checklist

  • ✓LLM platform selected from the governed list, DPA / zero-retention terms on file, gateway in front of it
  • ✓SSO integrated; authorisation derived from EPM security groups; cookie gate removed
  • ✓Read-only EPM service account per pod, credential in a vault, rotation scheduled
  • ✓Prompts, schema, and eval set version-controlled and under change management
  • ✓Append-only audit log wired to the SIEM with the agreed retention
  • ✓Golden-query eval suite passing in CI; results archived as release evidence
  • ✓Dev / Test / Prod pipeline with gates, IaC, and a rehearsed rollback
  • ✓Model-risk register entry and owner named; first re-validation date set
  • ✓Metadata refresh job scheduled with change detection
  • ✓SLOs, cost caps, and the incident runbook agreed with platform operations
Plan a production rollout with us → Back to the demo