The problem this solves
Oracle SmartView is the standard tool for EPM data retrieval in Excel. It is also one of the most under-used tools in the Oracle ecosystem β not because it lacks power, but because building a good ad-hoc grid from scratch takes 10β15 minutes even for a SmartView-proficient analyst: connect, select the cube, place dimensions on rows and columns, suppress zeros, set POV, zoom in, format.
Most finance users end up with the same 3β4 saved grids and never adapt them β they pull more data than they need and manually filter in Excel. The result is stale, over-wide reports that answer a slightly different question than the one being asked.
The SmartView NLQ builder generates a ready-to-use grid template in natural language. The analyst types "Revenue accounts for Berlin Mitte FY26 plan vs actual quarterly" and receives a pre-built, formatted grid β including Oracle HsGetValue formulas that connect to a live EPM instance the moment the analyst opens the file in Excel.
Audience
Finance analysts and controllers who use Oracle SmartView for period-end reporting, budget book preparation, and scenario comparison. EPM support teams who spend time building and distributing standard grid templates. Finance managers who want self-service EPM access without SmartView training overhead.
Natural language grid requests
The input is a plain-text description of the desired grid. The NLQ parser extracts five axes:
| Axis | Recognises | Example |
|---|---|---|
| Accounts | Revenue accounts, OpEx, margin, P&L lines, account group names | "revenue accounts", "cost lines", "margin" |
| Entity | 44 stores/entities, 4 region rollups | "Berlin Mitte", "EMEA", "Toronto" |
| Scenarios | plan, actual, budget, forecast β up to two at once | "plan vs actual", "budget vs forecast" |
| Year | FY22βFY26 | "FY26", "this year" |
| Period | Q1βQ4, months, H1/H2, full year; "zoom in" to months | "quarterly", "monthly", "Q1βQ3" |
Interactive controls let the user modify the grid after NLQ generation: add/remove accounts via chips, switch between quarterly and monthly, toggle scenarios, and remove individual rows.
A live-ready Excel SmartView template
The primary output is a rendered grid in the browser β Account rows Γ Period Γ Scenario columns β styled to mirror Oracle SmartView output. The secondary output is the Excel file.
The Excel file contains
- Sheet 1 β Grid: Every data cell is a real
HsGetValueformula pointing to the user's EPM connection. Cell B1 holds the connection name. Data cells reference$B$1so changing the connection updates the whole sheet. - Sheet 2 β Connection Guide: Step-by-step instructions to connect SmartView to an Oracle EPM instance, keyboard shortcuts (F9 refresh, Ctrl+Shift+J zoom in), and troubleshooting notes for the three most common SmartView errors.
HsGetValue formula example
=HsGetValue($B$1,
"Account#Store Revenue",
"Entity#Berlin Mitte",
"Scenario#Plan",
"Year#FY26",
"Period#Q1",
"Currency#USD")
In your EPM + Excel workflow
SmartView NLQ sits between the EPM data model (source) and the analyst's Excel working file (destination). It does not replace the EPM data entry process or Oracle Analytics dashboards β it replaces the manual "build an ad-hoc grid from scratch" step that every SmartView user repeats several times per period.
- Budget book prep: FP&A team generates 44 store-level revenue grids in one session, each pre-wired to live EPM data
- Variance triage: Controller builds a focused grid (COGS accounts, Berlin Mitte, Q3 FY26 actual vs plan) in 30 seconds instead of navigating SmartView manually
- Template distribution: EPM support team generates standard grids with HsGetValue formulas and distributes them β no SmartView client install needed on the recipient's machine until they want to refresh
- New user onboarding: Finance users who aren't SmartView-trained get useful, pre-wired grids without needing SmartView configuration knowledge
The numbers
| Component | Choice |
|---|---|
| LLM | DeepSeek V3 β structured JSON grid spec from natural language |
| Excel | SheetJS (xlsx 0.18.5) β client-side .xlsx generation with formula support |
| Formula type | HsGetValue β Oracle SmartView standard formula, live EPM connection |
| Grid cache | Stored as cached value (v) + formula (f) in SheetJS cell object |
The honest checklist
- βYou have Oracle SmartView deployed and finance users who build ad-hoc grids regularly
- βYour users spend more than 10 minutes per period building standard grids they could describe in one sentence
- βYou want self-service EPM data access in Excel without SmartView training overhead for casual users
- βYou want live-data Excel files, not snapshots β HsGetValue connects directly to your EPM instance on F9
- βYou need complex suppress-zeros, asymmetric grids, or member formula rows β NLQ generates symmetric grids only
- βYou need writeback β HsGetValue is read-only; SmartView data form functionality is not replicated here
- βYour EPM cube has a non-standard dimension structure not reflected in the demo corpus
Try it now
The live demo generates real SmartView-ready Excel files with HsGetValue formulas. Download the file and open it in Excel with Oracle SmartView installed to see the formulas connect to a live EPM instance.
Sample queries to try
"Revenue accounts for Tokyo Shibuya FY26 plan vs actual""OpEx lines London Oxford St quarterly FY26""Show both scenarios Mumbai BKC FY26 monthly""APAC margin accounts FY25 budget vs forecast"
The template distribution problem
EPM support teams routinely spend 2β4 hours per period building and distributing standard SmartView grid templates for finance teams. Each template is a static Excel file β by the time it reaches analysts, the data is already stale. Analysts who want a slightly different view have to either request a new template (days of lead time) or build their own grid from scratch (20 minutes of SmartView configuration).
The NLQ approach inverts this: every analyst generates their own live-data template on demand, in under 30 seconds, and the file refreshes against live EPM data when they press F9 in Excel. The EPM support team's template-building workload drops to near zero.
Secondary value: the HsGetValue formula output is a forcing function for correct EPM query construction. Every formula has an explicitly named entity, account, scenario, year, and period β no ambiguous POV, no stale snapshot, no copy-paste errors.
NLQ β Grid spec β Excel pipeline
- Parses the query into a full grid specification
- Renders Account × Period × Scenario grid
- Interactive: add/remove rows, zoom in
- Toggle scenarios, switch quarterly/monthly
- Builds .xlsx with HsGetValue formulas
- POV header block (B1 = connection name)
- Frozen panes at col C / row 9
- Sheet 2: Connection Guide (8-step setup)
App UI β Component breakdown
| Component | Behaviour |
|---|---|
| Query bar | Full-width input, Enter to submit, 500-char max |
| Account chip strip | Post-NLQ: account names shown as removable chips; click to add accounts from a dropdown |
| Period toggle | Quarterly / Monthly switch β re-renders grid and updates all column headers |
| Scenario toggle | Plan / Actual / Both β adds or removes scenario columns |
| Grid table | Account rows Γ Period Γ Scenario columns; BvA column when both scenarios selected |
| Download Excel | Generates .xlsx via SheetJS with HsGetValue formulas + Connection Guide sheet |
| Connection input | User enters their SmartView connection name; substituted into all HsGetValue $B$1 references |
Account chips and the retail chart of accounts
The SmartView builder's default account chip set mirrors 7 of the 18 accounts in the shared FP&A income statement β the 3 revenue lines plus the four computed totals analysts ask for most often in ad-hoc grids:
| Group | Accounts |
|---|---|
| Revenue lines | Store Revenue, Digital Revenue, Wholesale & Franchise Revenue |
| Computed totals | Net Revenue, Gross Profit, EBITDA, Net Income (all Dynamic Calc) |
| Addable via chip picker | Merchandise Cost, Buying & Distribution, Store Labor, Store Occupancy, Marketing & Digital Ads, Technology & G&A, D&A, Interest Expense, Tax Provision |
Period granularity: Quarterly (Q1βQ4) or Monthly (JanβDec). Monthly mode generates 12 columns per scenario. Zoom-in from Q to Month is triggered by the period toggle β the account list is unchanged.
Grid spec extraction
The SmartView prompt differs from the FP&A prompt in one key way: it returns an array of accounts rather than a single statement type, and it supports two scenarios simultaneously.
// Output schema (SmartView variant)
{
"accounts": ["Store Revenue", "Digital Revenue", ...],
"accountGroup": "revenue" | "opex" | "margin" | "mixed",
"entity": "Berlin Mitte" | "APAC" | ...,
"scenarios": ["Plan", "Actual"], // 1 or 2 elements
"year": "FY26",
"periods": ["Q1","Q2","Q3","Q4"],
"periodGranularity": "quarterly" | "monthly",
"chartType": "bar" | "line" | null
}
Key prompt engineering decisions
- Account group inference: "revenue accounts" β accounts array contains all revenue-type members, not just "Total Revenue"
- Two-scenario handling: "plan vs actual" β scenarios array has exactly two elements; "actual" alone β one element
- Period granularity: "monthly" or "month-by-month" β
periodGranularity: "monthly"; default is quarterly
How the Excel export works
SheetJS (xlsx 0.18.5) supports formula cells via the cell object { t:'n', v:cachedValue, f:'HsGetValue(...)' }. The cached value v holds the demo data number β this makes the file usable immediately without an EPM connection. When the user opens it in Excel with SmartView and presses F9, the formula fires against their live EPM instance and replaces the cached value.
Cell structure
// SheetJS cell with HsGetValue formula
ws['D10'] = {
t: 'n',
v: 4230000, // cached demo value (shows without EPM connection)
f: 'HsGetValue($B$1,' +
'"Account#Store Revenue",' +
'"Entity#Berlin Mitte",' +
'"Scenario#Plan",' +
'"Year#FY26",' +
'"Period#Q1",' +
'"Currency#USD")'
};
POV header block (rows 1β7)
Rows 1β7 contain the POV setup: B1 = connection name (user-editable), B2 = Entity, B3 = Year, B4 = Currency, B5 = Cube name, B6 = Application name, B7 = Database name. All data formulas reference $B$1 for the connection β changing B1 re-points the entire sheet to a different EPM environment.
Freeze panes
Freeze at column C, row 9: account names stay visible while scrolling across 12 monthly columns; the POV block stays visible while scrolling down through account rows.
Cost per grid generation
| Component | Detail | Cost |
|---|---|---|
| LLM input tokens | ~950 tokens (system prompt ~750 + user query ~200) | $0.000133 |
| LLM output tokens | ~200 tokens (accounts array is larger than IS/BS/CF JSON) | $0.000056 |
| SheetJS Excel generation | Client-side (browser) β zero server cost | $0 |
| Total per grid | ~$0.000189 | |
| With 2Γ safety margin | ~$0.0004 |
Cost model β At-scale projections
| Scale | Grids/day | Monthly cost | Notes |
|---|---|---|---|
| FP&A team (10 users) | 30 | $0.36 | 3 grids/user/day, period-end spike 2Γ |
| Finance dept (100 users) | 200 | $2.40 | Heavy month-end usage included |
| Enterprise (1,000 users) | 1,500 | $18 | Replace all manual SmartView template requests |
Key files
| File | Role |
|---|---|
epm-nlq-src/pages/smartview.html | UI, grid renderer, account chip strip, period toggle, scenario toggle, and downloadExcel() function |
functions/api/nlq-query.js | Shared NLQ endpoint; SmartView uses the same function as FP&A with a different system prompt branch triggered by the mode: "smartview" parameter |
epm-nlq-src/assets/epm-data.js | DIMENSION_MEMBERS provides the cached values for HsGetValue formulas (displayed before EPM connection is made) |
The downloadExcel() function
The function builds the workbook in memory using SheetJS, iterating over account rows Γ period Γ scenario columns to construct each formula string. The connection name from the input box (or default "HFM" if blank) is placed in B1. The Connection Guide sheet is built from a static array of step objects β no external template file required. The workbook is serialised and downloaded as EPM-SmartView-[Entity]-[Year].xlsx.
Tech stack β Every tool in this build
| Layer | Tool | Why |
|---|---|---|
| LLM | DeepSeek V3 | OpenAI-compatible JSON mode, array output support, low cost |
| Excel engine | SheetJS xlsx 0.18.5 | Client-side .xlsx with formula cells (t:'n', v:cachedVal, f:'HsGetValue...'). No server upload needed. |
| Formula standard | Oracle HsGetValue | Native SmartView formula; connects to EPM instance on F9 refresh |
| Edge runtime | Cloudflare Pages Functions | Zero cold start, shared with FP&A NLQ endpoint |
| Data layer | epm-data.js DIMENSION_MEMBERS | Provides cached values for formula cells (shown before EPM connection) |
| Build | Eleventy v3.1.5 | Copies epm-nlq-src/pages/ to _site/ verbatim |
Known attack surfaces
| Threat | Mitigation |
|---|---|
| Formula injection in Excel output | All formula strings are constructed server-side from validated enum values only β no user text is interpolated into HsGetValue formula strings |
| Connection name injection | Connection name from UI is used only in cell B1 as a plain string, not in formula construction. Formula references only $B$1 β not the string value directly. |
| Prompt injection | Same guardrail as FP&A: LLM returns structured JSON only; injected prose has no output channel |
| Large grid DoS | Account array capped at 30 rows, period columns capped at 12 (monthly mode) |
Guardrails β What prevents bad grids
- Account enum validation: Only accounts in the known DIMENSION_MEMBERS corpus are allowed in the output array. Unknown account names from the LLM are filtered out before grid rendering.
- Two-scenario limit: Even if the user asks for three scenarios, the parser returns a maximum of two (Plan + Actual, or the two most mentioned). More than two columns per period makes grids unreadable.
- Period granularity guard: Monthly mode is only available when the period set is full-year (all 12 months or Q1βQ4). Requesting "monthly Q3 only" is re-interpreted as "quarterly Q3 only".
- Empty result guard: If the account array resolves to zero valid accounts, the UI shows an error with suggested account group names β it does not render an empty grid.
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.
9.1 · The identity chain, end to end
- 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
- 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
- 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
- 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
- Roles: Service Administrator, Power User, User, Viewer — assigned to groups, never to individuals
- Data level: Enforced twice: once when this tool builds the template, and again — authoritatively — when the user refreshes the workbook and SmartView retrieves under their own login
- Group → role mapping lives in the platform, not in this application
- 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 provider | Protocol | Notes |
|---|---|---|
| Microsoft Entra ID (formerly Azure AD) | SAML 2.0 or OIDC | The 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. |
| Okta | SAML 2.0 or OIDC | Same pattern; Okta groups drive EPM roles through SCIM provisioning. |
| OCI IAM (identity domains) | Native | Already 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 FS | SAML 2.0 | Still 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: Planning User, plus a SmartView connection pointed at the same identity domain.
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 propagation | Pattern B — service account + filtering | |
|---|---|---|
| How | The user’s token is exchanged (OAuth 2.0 on-behalf-of) for one scoped to the EPM API; calls are made as the user | A single read-only integration account calls the API; the application filters the results |
| Enforcement point | Oracle EPM Cloud | This application |
| Audit trail shows | The real end user | The service account — you must log the real user separately |
| Failure mode | Token plumbing is more complex; per-user rate limits apply | A filtering bug is a data breach, and the entitlement copy drifts from reality |
| Verdict | Prefer this wherever the API supports user-token authentication | Acceptable 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: Enforced twice: once when this tool builds the template, and again — authoritatively — when the user refreshes the workbook and SmartView retrieves under their own login.
- 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 SmartView Builder
| Concern | Answer for this use case |
|---|---|
| Native entitlement required | Planning User, plus a SmartView connection pointed at the same identity domain |
| Data-level control | Enforced twice: once when this tool builds the template, and again — authoritatively — when the user refreshes the workbook and SmartView retrieves under their own login |
| Use-case-specific sensitivity | This is the one use case where the artifact outlives the session. The generated workbook contains HsGetValue formulas, not values, so a workbook forwarded to a colleague returns their data on refresh, not the author’s. Say that explicitly in training — people assume a shared file leaks the numbers, and here it does not. |
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
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 SmartView Builder 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.
10.1 · Production reference architecture
- 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
- 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
- Data stays inside the OCI boundary
- Natural fit when EPM is already in OCI
- Use the hyperscaler the org already governs
- Enterprise DPA, no training on prompts
- For regulated or sovereign data
- Highest control, highest run cost
- Oracle EPM Planning — metadata (accounts, periods, scenarios) via REST; the generated workbook carries
HsGetValueformulas, so cell values are pulled by the user’s own SmartView connection at open time - 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
- 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
- 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.
| Option | Choose when | Data posture |
|---|---|---|
| Oracle OCI Generative AI (Cohere Command, Llama) | EPM Cloud already lives in OCI; you want one cloud boundary and one contract | Prompts stay in the OCI tenancy; no training on customer data; dedicated AI clusters available for isolation |
| Azure OpenAI Service | Microsoft-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 audited | VPC/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 signed | ZDR 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 inference | Full 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
| Control | Implementation |
|---|---|
| Identity & access | Covered 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 account | One 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 & config | No secrets in code or build artifacts; environment-specific config injected at deploy; .dev.vars-style files never leave a developer machine. |
| Network | Private 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 guardrails | Layer 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 guardrails | Layer 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 minimisation | Prompts 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. |
| Encryption | In 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.
| Requirement | How it is satisfied |
|---|---|
| Complete, immutable audit trail | Append-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 management | Prompt 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 duties | Developers cannot deploy to production; the service-account owner is not a developer; production secrets are held by platform operations. |
| Access recertification | Quarterly review of who can use the tool and of the service account’s EPM roles, evidenced and signed. |
| Testing evidence | A 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 management | An 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 & lineage | Every 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. |
| Explainability | The 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
| Environment | EPM target | Data | Gate to leave |
|---|---|---|---|
| Dev | EPM Test pod (developer slice) | Synthetic or masked | Unit tests on the data layer; lint; eval suite ≥ threshold against the Test LLM deployment |
| Test / UAT | EPM Test pod (full refresh) | Masked copy of production | Business UAT sign-off on the golden queries; security scan; performance run (p95 latency, fallback rate) |
| Prod | EPM Production pod | Live | Change 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 SmartView Builder
| Concern | Production answer |
|---|---|
| System of record | Oracle EPM Planning — metadata (accounts, periods, scenarios) via REST; the generated workbook carries HsGetValue formulas, so cell values are pulled by the user’s own SmartView connection at open time |
| Read/write posture | Read-only. The tool emits a template; EPM security is enforced by SmartView when the user refreshes. |
| Use-case-specific control | Govern the workbook as a template artifact: signed/approved connection names, no macros, and a naming convention so audit can tell a generated template from a hand-built one. |
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