The problem this solves

Oracle EPM Planning's metadata β€” the dimension hierarchies, member properties, aliases, data storage types, and parent-child relationships β€” is typically only accessible to EPM administrators with direct access to the Oracle Enterprise Data Management (EDM) module or the Planning metadata console. A finance analyst who wants to understand why a number looks different from what they expected has no self-service way to answer the question: "Is this account a Dynamic Calc? What's its parent? Is it in the right hierarchy?"

The result is a constant stream of metadata questions to the EPM team. "Which store is under EMEA?" "What accounts roll up to Net Revenue?" "Is the Store Occupancy account a leaf or a parent?" These are 2-minute questions that take 2 days to get answered through a ticket queue.

Master Data NLQ gives finance and operations users direct natural-language access to the EPM dimension metadata β€” without needing admin rights, without reading FDMEE documentation, and without waiting for the EPM team. The 12-dimension hierarchy of a full Planning cube is fully traversable in plain English.

Audience

Finance analysts who need to understand the EPM data model to interpret their reports. EPM business analysts performing metadata audits or impact analysis. EPM architects documenting a Planning application's dimension structure. Finance managers onboarding to a new Planning application and needing to understand the account hierarchy.

Natural language metadata queries

Input is a plain-text question about the EPM Planning dimension structure. Three query modes are supported:

ModeExample queriesWhat it searches
Member search"Find all revenue accounts", "Which accounts start with 'Net'", "Search for members named Berlin"Member name, alias, description fields β€” case-insensitive, partial match
Hierarchy explore"Show stores under EMEA", "What are the children of Net Revenue?", "Show parent of Berlin Mitte"Parent-child relationships, depth-first traversal
Dimension stats"How many members in Account?", "What percentage are Dynamic Calc?", "Show member types for Entity"Data storage type breakdown (Store, Dynamic Calc, Label Only) per dimension

The parser also accepts cross-dimension queries: "Show all leaf members in APAC with their currency settings" β€” entity hierarchy + currency dimension combined.

Searchable dimension metadata in the browser

Three distinct output formats depending on query mode:

  • Search results table: Member name Β· Dimension Β· Parent Β· Data storage type Β· Alias Β· Description β€” sortable columns, highlight matched search term
  • Hierarchy tree: Expandable parent-child tree with indentation levels, member count, and data storage type badge per node. Leaf members show in italic; Dynamic Calc members show with a ⚑ badge.
  • Dimension statistics panel: For each queried dimension: total member count, breakdown by data storage type (Store Data / Dynamic Calc / Label Only) with a doughnut chart, and level-by-level member counts.

In the EPM governance workflow

Master Data NLQ sits alongside Oracle Enterprise Data Management (EDM) and the Planning metadata console, but it serves a different audience. EDM is for EPM administrators who manage the hierarchy. The metadata console is for technical users who need full control. Master Data NLQ is for business users who need to understand the hierarchy without changing it.

  • Report interpretation: Analyst sees an unexpected number, asks "What accounts roll up to Total OpEx?" to verify the hierarchy is configured as expected
  • Impact analysis: Business analyst asks "How many accounts are Dynamic Calc in the Account dimension?" before proposing a metadata change
  • New hire onboarding: New FP&A hire asks "Show me all EMEA entities" to understand the regional structure without needing admin access
  • Audit support: Internal audit team searches for all members with a specific alias or description pattern, across all 12 dimensions, in seconds

The numbers

12
EPM dimensions
10,500+
Total members
3
Query modes
$0.0002
Cost per query
0ms
Search latency (local)
EDM
Targets this workflow
DimensionMember countHierarchy depth
Account8004 levels
Store520 (incl. rollups)5 levels
Scenario151 level
Year121 level
Period283 levels
Currency38 (incl. ENTITY/PARENT)1 level
Version101 level
Merchandise7,2006 levels
Others (4)~1,880Varies

The honest checklist

  • βœ“You have Oracle EPM Planning with a multi-dimension structure that non-admin users struggle to understand
  • βœ“Your EPM team receives repeated metadata questions from finance users ("what accounts are under X?", "is Y a leaf member?")
  • βœ“You want self-service dimension exploration without giving finance users EPM admin rights
  • βœ“You are planning an EPM metadata audit and want a searchable corpus of your dimension members
  • βœ—You need writeback β€” EDM writeback (adding/moving members) is out of scope for NLQ; this is read-only metadata exploration
  • βœ—You need real-time metadata from your live EPM instance β€” the demo uses a pre-loaded corpus; production requires the EPM REST API metadata endpoint
  • βœ—You need access control per dimension or member β€” the demo shows all members to all authenticated users

Try it now

The live demo indexes 10,500+ EPM Planning members across 12 dimensions. Search, explore hierarchies, and view dimension statistics β€” all client-side, zero latency once loaded.

Launch Master Data NLQ β†’ Start a Lab engagement

Sample queries to try

  • "Find all revenue accounts"
  • "Show stores under APAC"
  • "What members are Dynamic Calc in Account?"
  • "How many dimensions does this cube have?"
HOW WE BUILT IT

The metadata question queue

In a typical Oracle EPM Planning deployment, the EPM team receives 10–20 metadata questions per week from finance users. "Which account does headcount roll up to?" "Is there a Currency dimension and what are the valid values?" "We're getting a data load error for entity 'Netherlands' β€” what's the exact member name?" Each question takes 5–10 minutes for the EPM analyst to look up and respond to β€” and the queue grows every time a finance team member is onboarded or the account hierarchy changes.

The Master Data NLQ layer makes the full dimension corpus self-service. The finance user asks the question in plain English and gets the answer in under 2 seconds. The EPM team's metadata support burden drops to near zero for lookup questions β€” they can focus on actual metadata governance and hierarchy changes.

The secondary business case is audit readiness. When an external auditor asks "Show us all accounts with a Dynamic Calc data storage type and their parent members," the answer is a 10-second query rather than a multi-day EPM export project.

Query-to-metadata pipeline

User query (metadata question)
1
Intent Parser
DeepSeek V3
{ mode, dimension, term, parent, filter }
  • Detects query mode: search | hierarchy | stats
  • Extracts: dimension, searchTerm, parentMember, dataStorageFilter
2
Metadata Engine
masterdata.html
  • Searches DIMENSION_MEMBERS corpus — client-side, zero latency
  • Search: fuzzy name/alias match
  • Hierarchy: depth-first tree traversal
  • Stats: member count by data storage type
3
Renderer
  • Search: sortable table, highlight match
  • Hierarchy: expandable tree with badges
  • Stats: doughnut chart + count table

The metadata engine (Layer 2) runs entirely client-side. Once the 10,500+ member corpus is loaded, all search and hierarchy operations are in-memory β€” sub-millisecond response time. Only the LLM intent parsing (Layer 1) requires a network call.

App UI β€” Component breakdown

ComponentBehaviour
Query barPlain-text metadata question, Enter to submit
Query mode tabsSearch Β· Hierarchy Β· Stats β€” auto-selected by LLM, overridable by user click
Dimension filterDropdown to scope search to a specific dimension (Account, Store, Scenario, etc.) or search all
Search results tableMember name Β· Dimension Β· Parent Β· Data storage Β· Alias. Sortable. Search term highlighted in yellow.
Hierarchy treeExpandable tree, indented levels, member count per parent, data storage badge (Store/DynCalc/LabelOnly)
Stats panelTotal members, doughnut chart by data storage type, level-by-level count table
Sample chip strip6 pre-written metadata query chips: revenue accounts, APAC stores, Dynamic Calc members, dimension count, Merchandise hierarchy, Currency values

The 12-dimension EPM Planning cube

The demo corpus models a full Oracle EPM Planning cube with the following dimensions:

DimensionTypeMembersNotes
AccountAccount800IS, BS, CF hierarchies; Dynamic Calc aggregations
StoreEntity5204 regions, 44 leaf stores/entities, Total Company rollup
ScenarioScenario15Plan, Actual, Forecast, Budget, Latest Estimate, Prior Year
YearYear12FY23–FY27 planning range
PeriodPeriod28Monthly + quarterly + half-year model
VersionGeneric10Working, Approved, Best Case, Worst Case, Management
CurrencyCurrency38USD, EUR, GBP, JPY, CNY, KRW, INR, AUD, CAD, BRL, MXN, SGD, AED, SAR, COP, CLP, ARS + ENTITY + PARENT
MerchandiseGeneric7,200Apparel/Footwear/Accessories/Beauty/Home/Sports hierarchy
Customer SegmentGeneric640Loyalty tiers, lifecycle stages, demographic cohorts
SupplierGeneric840Merchandise suppliers, logistics providers, vendor programs
ChannelGeneric120DTC (store + digital), Wholesale, Marketplace, Franchise, B2B
CampaignGeneric280Seasonal, promotional, loyalty, and brand campaigns by region

Data storage types in the corpus: Store Data (leaf-level numeric data), Dynamic Calc (computed on-the-fly from children β€” never explicitly stored), Label Only (hierarchy grouping node, no data).

How member search works

The search runs client-side against the pre-loaded dimension corpus. No server round-trip after the initial page load.

Search ranking (descending priority)

  1. Exact name match β€” member name equals search term (case-insensitive)
  2. Name starts with β€” member name starts with search term
  3. Name contains β€” search term appears anywhere in member name
  4. Alias match β€” same three-tier ranking applied to the alias field
  5. Description match β€” lowest priority, partial match in description text

Hierarchy traversal

Parent-child relationships are stored in a flat memberMap object keyed by member name, with children[] and parent fields. Hierarchy queries use depth-first traversal from the named parent, returning all descendants with their depth level. The tree renderer indents by 20px per level and collapses branches deeper than level 3 by default.

// Hierarchy traversal (simplified)
function getDescendants(memberName, depth = 0) {
  const member = memberMap[memberName];
  if (!member) return [];
  return [{ ...member, depth }].concat(
    (member.children || []).flatMap(
      c => getDescendants(c, depth + 1)
    )
  );
}

Metadata intent extraction

The Master Data NLQ prompt extracts the query mode and metadata parameters. It is the most intent-diverse prompt of the four use cases β€” three distinct query modes require three different output shapes:

// Output schema (Master Data variant)
{
  "mode": "search" | "hierarchy" | "stats",

  // search mode
  "searchTerm": "revenue",
  "dimension": "Account" | "Entity" | ... | "all",
  "dataStorageFilter": "Store" | "DynCalc" | "LabelOnly" | null,

  // hierarchy mode
  "parentMember": "EMEA",
  "dimension": "Entity",
  "direction": "children" | "parent" | "ancestors",

  // stats mode
  "dimension": "Account" | "all"
}

Mode detection rules (few-shot examples)

  • "find", "search", "which members", "show me accounts named" β†’ search
  • "children of", "what's under", "show hierarchy", "parent of" β†’ hierarchy
  • "how many", "count", "statistics", "breakdown", "percentage" β†’ stats

Cost per metadata query

ComponentDetailCost
LLM input tokens~700 tokens (smaller system prompt β€” no dimension value enums needed)$0.000098
LLM output tokens~100 tokens (compact mode + parameters JSON)$0.000028
Search executionClient-side in-memory β€” zero server cost$0
Total per query~$0.000126
With 2Γ— safety margin~$0.0003

The Master Data use case has the lowest per-query cost of the four because the system prompt is shorter (no dimension value enumerations β€” the corpus is searched client-side, not described to the LLM), and the output JSON is the most compact.

Cost model β€” At-scale projections

ScaleQueries/dayMonthly costNotes
EPM team (5 users)20$0.18Heavy admin usage during month-end
Finance + EPM (50 users)100$0.90Self-service replaces most metadata tickets
Organisation-wide (500 users)500$4.50All EPM stakeholders self-serve

Master Data NLQ has the lowest at-scale cost of the four use cases β€” smaller prompt, compact output, and the search itself runs client-side at zero cost. The main scaling consideration at enterprise scale is the initial corpus load time (10,500+ members is ~120KB of JSON) β€” at 10,000+ members a production deployment would use a server-side EPM REST API metadata call and client-side caching.

Key files

FileRole
epm-nlq-src/pages/masterdata.htmlFull metadata UI: search table with highlight, hierarchy tree renderer, stats doughnut chart, chip strip, query mode tabs
epm-nlq-src/assets/epm-data.jsDIMENSION_MEMBERS extended with member metadata: { name, alias, parent, children[], dataStorage, dimension, description }
functions/api/nlq-query.jsShared endpoint; Master Data uses mode:'masterdata' to select the metadata system prompt branch. LLM only extracts intent β€” all search runs client-side.

The memberMap construction

On page load, epm-data.js DIMENSION_MEMBERS is flattened into a memberMap object for O(1) member lookup by name. The map is built once and used for all search, hierarchy, and stats queries. Building the map for 10,500+ members takes ~2ms on a modern browser β€” imperceptible to the user.

Highlight rendering

Search term matches are highlighted using a DOM-safe text splitter β€” the search term is never inserted via innerHTML. Instead, the member name text node is split at match positions and wrapped with a <mark> element created via document.createElement. This prevents XSS via injected member names.

Tech stack β€” Every tool in this build

LayerToolWhy
LLMDeepSeek V3Mode classification + metadata parameter extraction. Smallest system prompt of the 4 use cases.
Search engineCustom JS (client-side)10,500+ member in-memory search is instant and free. No Elasticsearch or external search service required at demo scale.
Hierarchy traversalCustom recursive JSDepth-first DFS on the memberMap object. Depth cap prevents stack overflow on deep hierarchies.
Charts (stats)Chart.js 4.xShared with Analytics UC4; doughnut chart for data storage type breakdown
Edge runtimeCloudflare Pages FunctionsShared NLQ endpoint; mode:'masterdata' selects the metadata prompt branch
Data corpusepm-data.js DIMENSION_MEMBERSExtended with member metadata fields: parent, children[], dataStorage, dimension, alias
SecurityDOM createElement APIHighlight rendering avoids innerHTML for search term injection prevention
BuildEleventy v3.1.5masterdata.html copied to _site/ verbatim; no template processing needed

Known attack surfaces

ThreatMitigation
XSS via member name highlightingMember names are never inserted via innerHTML. Highlight uses createElement('mark') with textContent β€” no user input reaches innerHTML.
Corpus data exposureDIMENSION_MEMBERS is public demo data β€” no real customer data. Production: replace with server-side EPM REST API call; corpus never leaves the server.
Prompt injection via search termLLM extracts searchTerm as a string; it is then used client-side in a text comparison function, not in another LLM call or SQL query. No injection surface downstream.
Hierarchy traversal DoSTraversal depth is capped at 10 levels; result set is capped at 500 members. Prevents runaway recursion on malformed hierarchy data.

Guardrails β€” What prevents bad metadata responses

  • Mode fallback: If the LLM returns an unknown mode, the default is search with the raw user query as the search term β€” always produces a result, never errors silently.
  • Zero-result handling: If a search returns zero members, the UI shows "No members found for '[term]' in [dimension]" with suggestions: check spelling, try a shorter term, or browse the dimension stats.
  • Unknown parent guard: If the LLM returns a parentMember not found in the corpus, the hierarchy view shows an error: "Member '[name]' not found β€” check the exact member name in the search tab."
  • Stats dimension guard: If stats mode is requested for an unrecognised dimension name, it defaults to showing stats for all dimensions rather than erroring.
  • Depth cap: Trees deeper than 10 levels show a "…and N more members" expansion link rather than rendering all descendants at once.

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: Viewpoint and node-type permissions in EDMCS decide which dimensions, and which branches of a hierarchy, a user may even see
  • Group → role mapping lives in the platform, not in this application
Result, filtered to this user
masterdata.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: EDMCS Data Manager or Viewer on the relevant viewpoints — browsing a dimension requires View on its viewpoint.

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: Viewpoint and node-type permissions in EDMCS decide which dimensions, and which branches of a hierarchy, a user may even see.
  • 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 Master Data NLQ

ConcernAnswer for this use case
Native entitlement requiredEDMCS Data Manager or Viewer on the relevant viewpoints — browsing a dimension requires View on its viewpoint
Data-level controlViewpoint and node-type permissions in EDMCS decide which dimensions, and which branches of a hierarchy, a user may even see
Use-case-specific sensitivityMetadata is sensitive in its own right — the Entity hierarchy is the legal-entity structure and the Merchandise hierarchy can contain unreleased product families. Scope dimension browsing by group; a full chart-of-accounts export is a competitive-intelligence document even with no balances attached.

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 Master Data NLQ 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: the demo already sends only the schema and the user’s words to the LLM — never the financial values. Production must preserve that boundary exactly: the model resolves what to fetch, the EPM REST API fetches it under the user’s own security, and no cell value is ever part of a prompt.

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 EDMCS (or Planning dimension metadata) via REST — refreshed on a schedule into the client-side search corpus, with change detection so a stale hierarchy is visible, not silent
  • 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
masterdata.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 Master Data NLQ

ConcernProduction answer
System of recordOracle EDMCS (or Planning dimension metadata) via REST — refreshed on a schedule into the client-side search corpus, with change detection so a stale hierarchy is visible, not silent
Read/write postureRead-only. Hierarchy changes stay inside EDM request workflows; this tool never edits members.
Use-case-specific controlMetadata is sensitive in its own right (legal-entity structure, org design, unreleased products). Classify it and scope who may browse which dimensions.

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