Opportunities Extension 1.0.1
Browser extension that adds the "Opportunities Extension" shortcut to the permitted Oracle Fusion pages, retrieves opportunities, and displays them in a filterable table.
Development Structure
src/content/: page integration, modal shell, theme and content composition.src/background/: synchronous message registration and background composition.src/features/: opportunities, products, consumption, AI summaries, preferences and debug.src/auth/: credential-specific selection, reuse and session recovery.src/services/: Fusion/SPA operations and background HTTP/JSON transport.src/platform/: narrow browser messaging, cookies, tabs and storage adapters.src/shared/messages.js: names of the existing cross-context messages.scripts/build.mjs: generates browser-specific packages.tests/: isolated synthetic regression tests and a visual fixture.docs/: architecture/contracts and incremental refactoring record.dist/chromium/: output for Google Chrome and Microsoft Edge.dist/firefox/: output for Firefox.
Build
Use Node.js:
npm run build
The build recreates dist/chromium and dist/firefox from the same source.
Do not edit files under dist directly. Both targets use Manifest V3, with a
Chromium service worker and Firefox background scripts. The build composes classic
factory modules from scripts/sources.cjs into one isolated IIFE per execution
context. It serializes src/content/styles/redwood.css followed by the scoped
src/features/debug/styles.css, src/features/opportunities/styles.css,
src/features/install-base/styles.css, src/features/service-requests/styles.css
src/features/consumption/plan-detail.css and src/features/ratecard/styles.css at
build time. There is no
runtime module loader, browser-side eval, ES-module requirement or new dependency.
Tests and Maintenance
Each Cloud Consumption plan includes a Rate card button beside Contract ID.
It opens an animated right-side drawer with skeleton rows, an all-column search
and sortable headers. The drawer reuses the Cloud Consumption header component
with the title Rate Card, customer subtitle, and the active plan's Booking
Customer, Sold To Party Name, Contract ID, Header Status, Start Date and End Date.
There is no separate plan-number subtitle or nested Rate Card action; its Close button
dismisses only the drawer. requestRatecardByPlan sends the active plan's subPlanNum
as the payload's planNumber, with recordsSize: 10000, to the fixed SPA endpoint.
It uses the existing OCICONS-TS uiaasHeader.value in G2m-Authorization and is
logged in the Consumption debug category with the existing credential masking.
The eleven requested fields are displayed, including percentage discounts and
USD prices with at least four decimal places. Search includes raw and formatted
values; prices, quantities, percentages and dates sort by value. Only the drawer
table scrolls, horizontally when its available width is below 1100px.
Closing the drawer, changing plans or closing Cloud Consumption discards late UI
updates. Concurrent requests for the same plan are shared; reopening after completion
fetches again. Errors remain local. No new persisted cache, permissions, token
refresh or retries are added. The provided contract requests up to 10000 records;
the response's searchAfter is not used without a defined pagination contract.
tests/ratecard.test.cjs covers transport, formatting, filtering, sorting and
drawer lifecycle with synthetic responses and DOM, without launching browsers.
Cloud Consumption loads requestConsumptionPlanDetail for the active plan after
account plans arrive, independently of the chart. Selecting another plan loads
its subPlanNum on demand. The GET uses active=true and the raw OCICONS-TS
uiaasHeader.value in G2m-Authorization, through the existing consumer session.
Projection badges align with the chart container's left edge, while the
Quarterly/Monthly/Weekly/Daily controls stay on the right of the same header row:
red Forfeit, blue Overage.
Hover or keyboard focus reveals an interactive tooltip; clicking pins it for
access to the Order number links. Escape, Close, outside clicks, tab changes and
modal closure dismiss it. Each root line retains its nested clines details.
Only HTTPS order links on accountdashboard.oracle.com become clickable.
Amounts use the requested non-LC fields, formatted without inferring a local
currency. Details are kept only in the current modal, with in-flight deduplication
and local loading/empty/error states. Failed details do not block the chart.
The existing Consumption debug category includes this request.
The Service Requests action sits immediately after Installed Base below Customer.
Its dialog opens with skeleton rows and lists open SRs for the selected customer.
The background first calls requestAccountSummary with ACCP-TS, then uses its
id (not registryId) in the GET requestCustomerServiceRequest URL. The SR
credential is uiaasHeader.value from SPA-ORANGE, sent verbatim in
custsr-auth, without a Bearer prefix, regardless of uiaasHeader.label.
Pages of 40 are consolidated using totalResults, count
and offset. Concurrent clicks for the same customer share the in-flight query;
results are not cached, and closed/replaced dialogs ignore late responses.
The table maps Name/Registry ID from customer, Product Name from component,
and formats status as a badge and dates using the existing date formatter.
Debug contains a Service Requests category; credential headers are masked before
delivery to content. This feature adds no permissions or authentication retries.
The Installed Base action sits beside customer consumption below Customer. It
opens a skeleton dialog, then calls requestAccountSummary with ACCP-TS and uses
the returned registryId in requestInstallBase. The latter uses the SAIB-TS
uiaasHeader.label and uiaasHeader.value, and loads pages of 25 until hasMore
is false. Missing credentials, invalid collections and stalled pagination show
an error rather than partial results. These requests appear in debug; credential
headers in this flow are masked before delivery to the content script. No new
cache, permissions or session recovery logic is introduced. Amounts use two
decimal places without inferring a currency from the separate LC fields.
The opportunities table places product counts below Name and the customer consumption action below Customer, without a separate Actions column. Compact columns retain their values; Name and Customer share the remaining width while Owner is fixed at 132px. Both text cells reserve at least two text lines, and their controls stay anchored 10px above the row bottom, including while products load. Longer text can grow the row without overlapping controls. Horizontal scrolling is reserved for table containers below 1120px. The scoped table stylesheet does not change product-table column widths or the existing light/dark colors.
Product HTTP requests appear in Debug Requests (Ctrl+D) as soon as they start.
Each entry identifies the opportunity and page offset, stays running while
waiting for headers or the response body, and updates with HTTP status, response,
duration or error. Cache hits do not create HTTP entries. Product diagnostics
mask authorization and sensitive response headers before messaging the source
tab/frame; this change adds no timeout, retry or authentication behavior.
Debug tabs group Authentication, Opportunities, Products, AI, Consumption, Installed Base and Service Requests requests; unknown request types appear under Other. Only categories with entries are shown. All preserves the complete timeline. Every tab sorts by request start time, retaining original request IDs and showing start times in collapsed rows. Counts and running states update without changing the selected category or collapsing expanded details. Use arrow keys, Home and End to navigate the tabs.
npm test
npm run check
Tests use built-in Node.js modules and synthetic credentials, without real Fusion
requests. The characterization suite verifies manifests, source/output equality,
fiscal dates, payloads, preferences, pagination, cache/progress and both browser API
styles. Architecture tests enforce source inclusion, explicit factory dependencies,
isolated state and unchanged CSS. These complement consumption, session recovery
and AI suites. check also fails if generated packages are stale.
There is no separate lint configuration or runtime dependency installation.
See architecture and contracts and the incremental refactoring record for execution boundaries, authentication, storage, known risks and verification limits. Mock-based tests do not replace testing the installed extension in each browser.
Without npm, run node scripts/build.mjs, node scripts/test.cjs and
node scripts/build.mjs --check. Development checks were run with Node 24.19.0.
For a local UI smoke test, run node scripts/preview.mjs and open the loopback URL
printed by the command. The fixture uses synthetic opportunities, tokens, products,
AI text and consumption; unexpected requests fail closed. It does not authenticate
against Fusion or read real extension storage. /consumption-trend.html provides
a focused chart fixture. Stop the server with Ctrl+C when finished.
Release 1.0.0
- Paginated opportunity retrieval with filters for reference, customer, owner, status, stage, and text search.
- Column sorting, links to opportunities and accounts, opportunity number copying, and stage indicators.
- Opportunity type view preferences persisted in the browser.
- Background product retrieval with configurable caching, progress tracking, and expandable product details.
- Cloud consumption account-plan lookup from each opportunity, displayed in a tabbed detail modal.
- Light and dark themes based on Oracle Redwood.
- Separate outputs for Chromium/Edge and Firefox.
Release 1.0.1
- Retries the consumer token service when it returns HTTP 200 with an HTML fallback.
- Opens the SPA session page in an inactive temporary tab and closes it as soon as valid JSON is received.
- Limits the recovery flow to five attempts and records the session bootstrap details in debug mode.
Loading in Development Mode
Chrome or Microsoft Edge
- Open
chrome://extensionsoredge://extensions. - Enable Developer mode.
- Click Load unpacked.
- Select the
dist/chromiumfolder.
Firefox
- Open
about:debugging#/runtime/this-firefox. - Click Load Temporary Add-on.
- Select the
dist/firefox/manifest.jsonfile.
Supported Pages
https://eeho.fa.us2.oraclecloud.com/hcmUI/faces/FuseWelcomehttps://eeho.fa.us2.oraclecloud.com/fscmUI/faces/FuseWelcome
When it finds the #yourapps_groupNode_sales group, the extension adds the tile before the .flat-grid-cell.flat-grid-cell-addicon item. Clicking the tile opens the opportunities interface.