[
https://issues.apache.org/jira/browse/ATLAS-5389?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Prasad P. Pawar updated ATLAS-5389:
-----------------------------------
Description:
DAST scan findings on Atlas UI endpoints show that current browser resource
policy headers allow inline scripts, dynamic JavaScript evaluation, and inline
styles. Server-side work will introduce per-request nonce support; this ticket
covers React Dashboard UI only ({{{}/n3/{}}}).
h3. Scope
In scope
* React Dashboard ({{{}dashboard/{}}} module, served at {{{}/n3/index.html{}}})
* Client-side changes to work with nonce-based script/style policy
* Unit tests for new/changed React code
* Smoke validation of main dashboard flows under the updated policy
Out of scope
* Classic Dashboardv2 (Backbone UI at {{{}/index.html{}}})
* Server-side filter/header implementation (tracked separately)
* Login/error page templates in {{webapp/}}
h3. Problem (UI perspective)
Under the planned strict policy:
# Inline scripts in HTML shell — must receive a server-injected nonce or be
externalized.
# MUI/Emotion runtime {{<style>}} tags — must use the same nonce as the CSP
header, or styles will be blocked.
# Lineage tooltip HTML — uses inline {{style=}} attributes in dynamically
built strings; may need CSS class migration.
React {{{}style={{}}}} props and MUI {{sx=}} are handled differently: {{sx}}
goes through Emotion (needs nonce); {{{}style={{}}}} is governed by
{{style-src-attr}} (server policy decision, no React code change if
transitional allowance is kept).
h3. Planned Fix
Phase 1 — Client nonce wiring (P0)
* Add {{dashboard/src/utils/cspNonce.ts}} to read nonce from {{<meta
name="csp-nonce">}} or the first {{<script nonce="...">}} tag.
* Update {{{}dashboard/src/Main.tsx{}}}:
** Create Emotion cache with {{createCache(\{ key: 'css', nonce: getCspNonce()
})}}
** Wrap app in {{CacheProvider}} + {{StyledEngineProvider}}
* Add unit tests: {{{}cspNonce.test.ts{}}}, update {{Main.test.tsx}}
Phase 2 — Inline content cleanup (P1)
* Refactor lineage tooltip inline styles in
{{dashboard/src/views/Lineage/atlas-lineage/src/index.js}} to CSS classes.
* Review {{dangerouslySetInnerHTML}} usage in {{commonComponents.tsx}} and
related components (content handling, not policy headers).
Phase 3 — Validation (P0)
* Smoke test: login → search → entity detail → lineage → admin → statistics.
* Confirm no browser console policy violations on {{/n3/}} routes.
* Update test documentation.
h3. Files to change (approx.)
||File||Change||
|{{dashboard/src/utils/cspNonce.ts}}|New — nonce reader utility|
|{{dashboard/src/utils/_{_}tests{_}_/cspNonce.test.ts}}|New — unit tests|
|{{dashboard/src/Main.tsx}}|Wire Emotion cache with nonce|
|{{dashboard/src/_{_}tests{_}_/Main.test.tsx}}|Assert nonce wiring|
|{{dashboard/src/views/Lineage/atlas-lineage/src/index.js}}|Replace inline
tooltip styles with CSS classes|
|{{dashboard/index.html}}|Optional {{<meta name="csp-nonce">}} placeholder for
server injection|
Estimated total: ~6–8 files, ~150 lines of change
h3. Dependencies
* Server must deploy per-request nonce generation and HTML nonce injection
before this UI work is validated in an integrated environment.
* Vite build already externalizes JS bundles; no build pipeline changes
expected.
h3. Acceptance Criteria
* React Dashboard loads and renders correctly at {{/n3/index.html}} under
nonce-based policy
* MUI/Emotion components render without blocked styles
* No browser console policy violations on primary user flows
* Unit tests added/updated for {{cspNonce.ts}} and {{Main.tsx}}
* Lineage tooltips display correctly after CSS class
h2. Manual Testing Guide
h3. Prerequisites
** Atlas server running (local or dev environment)
** Backend CSP changes deployed (PR #742 or equivalent with HTML nonce
injection)
** Browser DevTools (Chrome/Firefox)
** Valid Atlas login credentials
----
h3. Part 1: Server-Side Verification
h4. Step 1 — Check CSP response header
curl -I -k -u admin:admin \
https://localhost:21000/n3/index.html
Expected response header:
Content-Security-Policy: default-src 'self'; script-src 'self'
'nonce-AbCdEf123456' blob:; style-src 'self' 'nonce-AbCdEf123456'; ...
Verify:
** No {{'unsafe-inline'}} in {{script-src}}
** No {{'unsafe-eval'}} in {{script-src}}
** {{'nonce-...'}} present in both {{script-src}} and {{style-src}}
Example (good):
Content-Security-Policy: default-src 'self'; script-src 'self'
'nonce-Xk9mP2qR7sT4' blob:; connect-src 'self'; img-src 'self' blob: data:;
style-src 'self' 'nonce-Xk9mP2qR7sT4'; font-src 'self' data:; object-src
'none'; base-uri 'self'; frame-ancestors 'none';
Example (bad — would fail DAST):
Content-Security-Policy: ... script-src 'self' 'unsafe-inline' 'unsafe-eval' ...
----
h4. Step 2 — Check HTML nonce injection
curl -k -u admin:admin \
https://localhost:21000/n3/index.html|grep-E'csp-nonce|nonce='
Expected output (once backend HTML injection is in place):
<meta name="csp-nonce" content="Xk9mP2qR7sT4" />
<script type="module" nonce="Xk9mP2qR7sT4" crossorigin
src="./assets/index-xxx.js"></script>
Verify:
** Meta {{content}} matches CSP header nonce (without {{nonce-}} prefix)
** Script tags have {{nonce="..."}} attribute
** Nonce value is the same across meta, script, and header
----
h4. Step 3 — Confirm nonce consistency per request
Run twice and compare:
curl -I -k -u admin:admin https://localhost:21000/n3/index.html 2>&1 | grep -i
content-security-policy
curl -I -k -u admin:admin https://localhost:21000/n3/index.html 2>&1 | grep -i
content-security-policy
Expected: Different nonce on each request (per-request generation).
----
h4. Step 4 — Check login page (backend scope)
curl -k https://localhost:21000/login.jsp 2>&1 | grep -E 'csp-nonce|nonce='
Login page CSP is backend-owned; confirm it is in scope for the backend PR.
----
h3. Part 2: UI-Side Verification (Browser)
h4. Step 1 — Open React Dashboard
## Log in to Atlas
## Navigate to React UI: {{https://<host>:<port>/n3/index.html}}
## Open DevTools → Console tab
Expected: No Content Security Policy violation errors.
Example violation (if broken):
Refused to apply inline style because it violates the following Content
Security Policy directive: "style-src 'self' 'nonce-...'".
----
h4. Step 2 — Verify nonce is read by the app
In DevTools Console, run:
// Check meta tag
document.querySelector('meta[name="csp-nonce"]')?.getAttribute('content')
// Check script nonce
document.querySelector('script[nonce]')?.getAttribute('nonce')
// Check Emotion style tags have nonce
document.querySelectorAll('style[data-emotion]').forEach(s =>
console.log(s.getAttribute('nonce')))
Expected (with backend deployed):
"Xk9mP2qR7sT4" // meta content
"Xk9mP2qR7sT4" // script nonce
"Xk9mP2qR7sT4" // emotion style nonce (multiple style tags)
"Xk9mP2qR7sT4"
...
Expected (local dev without backend injection):
"" // empty meta — app still loads, no nonce on styles
undefined // no script nonce
null // emotion styles without nonce (OK in dev without strict CSP)
----
h4. Step 3 — Visual smoke test
||#||Flow||What to check||
|1|Dashboard home|Cards, charts, sidebar render with correct MUI styling|
|2|Search|Search bar, filters, results table styled correctly|
|3|Entity detail|Tabs, properties, labels render properly|
|4|Lineage tab|Graph renders (note: tooltip inline styles are a follow-up)|
|5|Admin → Type system|Tree view, MUI components styled|
|6|Toast notifications|Trigger an action that shows a toast — styled correctly|
Expected: No unstyled/broken UI. No console CSP errors.
----
h4. Step 4 — Network tab verification
## DevTools → Network tab
## Reload {{/n3/index.html}}
## Click the document request → Headers
Check Response Headers:
content-security-policy: ... 'nonce-AbCdEf123456' ...
Check Response body (Preview):
<meta name="csp-nonce" content="AbCdEf123456" />
Confirm header nonce ({{{}nonce-AbCdEf123456{}}}) matches meta content
({{{}AbCdEf123456{}}}).
----
h4. Step 5 — Simulate strict CSP locally (optional, advanced)
For local UI testing before backend is ready:
## Start dev server:
cd dashboard && npm run dev
## Temporarily edit {{{}dashboard/index.html{}}}:
<meta name="csp-nonce" content="test-local-nonce" />
## Add a strict CSP meta tag for testing:
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'nonce-test-local-nonce';
style-src 'self' 'nonce-test-local-nonce'; connect-src 'self' ws://localhost:*
http://localhost:*;"/>
## Open {{http://localhost:5173/n3/}}
## In Console, verify:
document.querySelector('meta[name="csp-nonce"]').content
// → "test-local-nonce"
[...document.querySelectorAll('style[data-emotion]')].every(
s=>s.getAttribute('nonce')==='test-local-nonce'
)
// → true (if UI changes are working)
Expected: Dashboard renders fully styled with zero CSP console errors.
----
h3. Part 3: End-to-End Checklist
||#||Test||Server||UI||Pass criteria||
|1|CSP header has nonce, no unsafe directives|curl -I|—|Header contains
{{{}'nonce-...'{}}}, no {{'unsafe-inline'}}|
|2|HTML meta tag populated|curl HTML|DevTools|Meta content matches header nonce|
|3|Script tags have nonce|curl HTML|DevTools|{{nonce="..."}} on module scripts|
|4|Emotion styles have nonce|—|DevTools|All {{style[data-emotion]}} have
matching nonce|
|5|Dashboard renders|—|Browser|No broken/unstyled UI|
|6|No console CSP errors|—|Browser|Console clean on all flows|
|7|Search works|—|Browser|Functional + styled|
|8|Entity detail works|—|Browser|Tabs, properties render|
|9|Login page works|curl|Browser|Backend scope — no blocked scripts|
was:
DAST scan findings on Atlas UI endpoints show that current browser resource
policy headers allow inline scripts, dynamic JavaScript evaluation, and inline
styles. Server-side work will introduce per-request nonce support; this ticket
covers React Dashboard UI only ({{{}/n3/{}}}).
h3. Scope
In scope
* React Dashboard ({{{}dashboard/{}}} module, served at {{{}/n3/index.html{}}})
* Client-side changes to work with nonce-based script/style policy
* Unit tests for new/changed React code
* Smoke validation of main dashboard flows under the updated policy
Out of scope
* Classic Dashboardv2 (Backbone UI at {{{}/index.html{}}})
* Server-side filter/header implementation (tracked separately)
* Login/error page templates in {{webapp/}}
h3. Problem (UI perspective)
Under the planned strict policy:
# Inline scripts in HTML shell — must receive a server-injected nonce or be
externalized.
# MUI/Emotion runtime {{<style>}} tags — must use the same nonce as the CSP
header, or styles will be blocked.
# Lineage tooltip HTML — uses inline {{style=}} attributes in dynamically
built strings; may need CSS class migration.
React {{style=\{{}}}} props and MUI {{sx={}}} are handled differently: {{sx}}
goes through Emotion (needs nonce); {{style=\{{}}}} is governed by
{{style-src-attr}} (server policy decision, no React code change if
transitional allowance is kept).
h3. Planned Fix
Phase 1 — Client nonce wiring (P0)
* Add {{dashboard/src/utils/cspNonce.ts}} to read nonce from {{<meta
name="csp-nonce">}} or the first {{<script nonce="...">}} tag.
* Update {{{}dashboard/src/Main.tsx{}}}:
** Create Emotion cache with {{createCache(\{ key: 'css', nonce: getCspNonce()
})}}
** Wrap app in {{CacheProvider}} + {{StyledEngineProvider}}
* Add unit tests: {{{}cspNonce.test.ts{}}}, update {{Main.test.tsx}}
Phase 2 — Inline content cleanup (P1)
* Refactor lineage tooltip inline styles in
{{dashboard/src/views/Lineage/atlas-lineage/src/index.js}} to CSS classes.
* Review {{dangerouslySetInnerHTML}} usage in {{commonComponents.tsx}} and
related components (content handling, not policy headers).
Phase 3 — Validation (P0)
* Smoke test: login → search → entity detail → lineage → admin → statistics.
* Confirm no browser console policy violations on {{/n3/}} routes.
* Update test documentation.
h3. Files to change (approx.)
||File||Change||
|{{dashboard/src/utils/cspNonce.ts}}|New — nonce reader utility|
|{{dashboard/src/utils/__tests__/cspNonce.test.ts}}|New — unit tests|
|{{dashboard/src/Main.tsx}}|Wire Emotion cache with nonce|
|{{dashboard/src/__tests__/Main.test.tsx}}|Assert nonce wiring|
|{{dashboard/src/views/Lineage/atlas-lineage/src/index.js}}|Replace inline
tooltip styles with CSS classes|
|{{dashboard/index.html}}|Optional {{<meta name="csp-nonce">}} placeholder for
server injection|
Estimated total: ~6–8 files, ~150 lines of change
h3. Dependencies
* Server must deploy per-request nonce generation and HTML nonce injection
before this UI work is validated in an integrated environment.
* Vite build already externalizes JS bundles; no build pipeline changes
expected.
h3. Acceptance Criteria
* React Dashboard loads and renders correctly at {{/n3/index.html}} under
nonce-based policy
* MUI/Emotion components render without blocked styles
* No browser console policy violations on primary user flows
* Unit tests added/updated for {{cspNonce.ts}} and {{Main.tsx}}
* Lineage tooltips display correctly after CSS class migration
> Atlas React Dashboard — Align UI with strict browser resource policy
> (nonce-based script/style handling)
> --------------------------------------------------------------------------------------------------------
>
> Key: ATLAS-5389
> URL: https://issues.apache.org/jira/browse/ATLAS-5389
> Project: Atlas
> Issue Type: Bug
> Components: atlas-webui
> Reporter: Prasad P. Pawar
> Assignee: Prasad P. Pawar
> Priority: Major
>
> DAST scan findings on Atlas UI endpoints show that current browser resource
> policy headers allow inline scripts, dynamic JavaScript evaluation, and
> inline styles. Server-side work will introduce per-request nonce support;
> this ticket covers React Dashboard UI only ({{{}/n3/{}}}).
> h3. Scope
> In scope
> * React Dashboard ({{{}dashboard/{}}} module, served at
> {{{}/n3/index.html{}}})
> * Client-side changes to work with nonce-based script/style policy
> * Unit tests for new/changed React code
> * Smoke validation of main dashboard flows under the updated policy
> Out of scope
> * Classic Dashboardv2 (Backbone UI at {{{}/index.html{}}})
> * Server-side filter/header implementation (tracked separately)
> * Login/error page templates in {{webapp/}}
> h3. Problem (UI perspective)
> Under the planned strict policy:
> # Inline scripts in HTML shell — must receive a server-injected nonce or be
> externalized.
> # MUI/Emotion runtime {{<style>}} tags — must use the same nonce as the CSP
> header, or styles will be blocked.
> # Lineage tooltip HTML — uses inline {{style=}} attributes in dynamically
> built strings; may need CSS class migration.
>
> React {{{}style={{}}}} props and MUI {{sx=}} are handled differently: {{sx}}
> goes through Emotion (needs nonce); {{{}style={{}}}} is governed by
> {{style-src-attr}} (server policy decision, no React code change if
> transitional allowance is kept).
> h3. Planned Fix
> Phase 1 — Client nonce wiring (P0)
> * Add {{dashboard/src/utils/cspNonce.ts}} to read nonce from {{<meta
> name="csp-nonce">}} or the first {{<script nonce="...">}} tag.
> * Update {{{}dashboard/src/Main.tsx{}}}:
> ** Create Emotion cache with {{createCache(\{ key: 'css', nonce:
> getCspNonce() })}}
> ** Wrap app in {{CacheProvider}} + {{StyledEngineProvider}}
> * Add unit tests: {{{}cspNonce.test.ts{}}}, update {{Main.test.tsx}}
> Phase 2 — Inline content cleanup (P1)
> * Refactor lineage tooltip inline styles in
> {{dashboard/src/views/Lineage/atlas-lineage/src/index.js}} to CSS classes.
> * Review {{dangerouslySetInnerHTML}} usage in {{commonComponents.tsx}} and
> related components (content handling, not policy headers).
> Phase 3 — Validation (P0)
> * Smoke test: login → search → entity detail → lineage → admin → statistics.
> * Confirm no browser console policy violations on {{/n3/}} routes.
> * Update test documentation.
> h3. Files to change (approx.)
> ||File||Change||
> |{{dashboard/src/utils/cspNonce.ts}}|New — nonce reader utility|
> |{{dashboard/src/utils/_{_}tests{_}_/cspNonce.test.ts}}|New — unit tests|
> |{{dashboard/src/Main.tsx}}|Wire Emotion cache with nonce|
> |{{dashboard/src/_{_}tests{_}_/Main.test.tsx}}|Assert nonce wiring|
> |{{dashboard/src/views/Lineage/atlas-lineage/src/index.js}}|Replace inline
> tooltip styles with CSS classes|
> |{{dashboard/index.html}}|Optional {{<meta name="csp-nonce">}} placeholder
> for server injection|
> Estimated total: ~6–8 files, ~150 lines of change
> h3. Dependencies
> * Server must deploy per-request nonce generation and HTML nonce injection
> before this UI work is validated in an integrated environment.
> * Vite build already externalizes JS bundles; no build pipeline changes
> expected.
> h3. Acceptance Criteria
> * React Dashboard loads and renders correctly at {{/n3/index.html}} under
> nonce-based policy
> * MUI/Emotion components render without blocked styles
> * No browser console policy violations on primary user flows
> * Unit tests added/updated for {{cspNonce.ts}} and {{Main.tsx}}
> * Lineage tooltips display correctly after CSS class
> h2. Manual Testing Guide
> h3. Prerequisites
> ** Atlas server running (local or dev environment)
> ** Backend CSP changes deployed (PR #742 or equivalent with HTML nonce
> injection)
> ** Browser DevTools (Chrome/Firefox)
> ** Valid Atlas login credentials
> ----
> h3. Part 1: Server-Side Verification
> h4. Step 1 — Check CSP response header
> curl -I -k -u admin:admin \
> https://localhost:21000/n3/index.html
> Expected response header:
> Content-Security-Policy: default-src 'self'; script-src 'self'
> 'nonce-AbCdEf123456' blob:; style-src 'self' 'nonce-AbCdEf123456'; ...
>
> Verify:
> ** No {{'unsafe-inline'}} in {{script-src}}
> ** No {{'unsafe-eval'}} in {{script-src}}
> ** {{'nonce-...'}} present in both {{script-src}} and {{style-src}}
> Example (good):
> Content-Security-Policy: default-src 'self'; script-src 'self'
> 'nonce-Xk9mP2qR7sT4' blob:; connect-src 'self'; img-src 'self' blob: data:;
> style-src 'self' 'nonce-Xk9mP2qR7sT4'; font-src 'self' data:; object-src
> 'none'; base-uri 'self'; frame-ancestors 'none';
>
> Example (bad — would fail DAST):
> Content-Security-Policy: ... script-src 'self' 'unsafe-inline' 'unsafe-eval'
> ...
>
> ----
> h4. Step 2 — Check HTML nonce injection
> curl -k -u admin:admin \
> https://localhost:21000/n3/index.html|grep-E'csp-nonce|nonce='
>
> Expected output (once backend HTML injection is in place):
> <meta name="csp-nonce" content="Xk9mP2qR7sT4" />
> <script type="module" nonce="Xk9mP2qR7sT4" crossorigin
> src="./assets/index-xxx.js"></script>
>
> Verify:
> ** Meta {{content}} matches CSP header nonce (without {{nonce-}} prefix)
> ** Script tags have {{nonce="..."}} attribute
> ** Nonce value is the same across meta, script, and header
> ----
> h4. Step 3 — Confirm nonce consistency per request
> Run twice and compare:
> curl -I -k -u admin:admin https://localhost:21000/n3/index.html 2>&1 | grep
> -i content-security-policy
> curl -I -k -u admin:admin https://localhost:21000/n3/index.html 2>&1 | grep
> -i content-security-policy
>
> Expected: Different nonce on each request (per-request generation).
> ----
> h4. Step 4 — Check login page (backend scope)
> curl -k https://localhost:21000/login.jsp 2>&1 | grep -E 'csp-nonce|nonce='
>
> Login page CSP is backend-owned; confirm it is in scope for the backend PR.
> ----
> h3. Part 2: UI-Side Verification (Browser)
> h4. Step 1 — Open React Dashboard
> ## Log in to Atlas
> ## Navigate to React UI: {{https://<host>:<port>/n3/index.html}}
> ## Open DevTools → Console tab
> Expected: No Content Security Policy violation errors.
> Example violation (if broken):
> Refused to apply inline style because it violates the following Content
> Security Policy directive: "style-src 'self' 'nonce-...'".
>
> ----
> h4. Step 2 — Verify nonce is read by the app
> In DevTools Console, run:
> // Check meta tag
> document.querySelector('meta[name="csp-nonce"]')?.getAttribute('content')
>
> // Check script nonce
> document.querySelector('script[nonce]')?.getAttribute('nonce')
>
> // Check Emotion style tags have nonce
> document.querySelectorAll('style[data-emotion]').forEach(s =>
> console.log(s.getAttribute('nonce')))
>
> Expected (with backend deployed):
> "Xk9mP2qR7sT4" // meta content
> "Xk9mP2qR7sT4" // script nonce
> "Xk9mP2qR7sT4" // emotion style nonce (multiple style tags)
> "Xk9mP2qR7sT4"
> ...
>
> Expected (local dev without backend injection):
> "" // empty meta — app still loads, no nonce on styles
> undefined // no script nonce
> null // emotion styles without nonce (OK in dev without strict CSP)
>
> ----
> h4. Step 3 — Visual smoke test
> ||#||Flow||What to check||
> |1|Dashboard home|Cards, charts, sidebar render with correct MUI styling|
> |2|Search|Search bar, filters, results table styled correctly|
> |3|Entity detail|Tabs, properties, labels render properly|
> |4|Lineage tab|Graph renders (note: tooltip inline styles are a follow-up)|
> |5|Admin → Type system|Tree view, MUI components styled|
> |6|Toast notifications|Trigger an action that shows a toast — styled
> correctly|
> Expected: No unstyled/broken UI. No console CSP errors.
> ----
> h4. Step 4 — Network tab verification
> ## DevTools → Network tab
> ## Reload {{/n3/index.html}}
> ## Click the document request → Headers
> Check Response Headers:
> content-security-policy: ... 'nonce-AbCdEf123456' ...
> Check Response body (Preview):
> <meta name="csp-nonce" content="AbCdEf123456" />
> Confirm header nonce ({{{}nonce-AbCdEf123456{}}}) matches meta content
> ({{{}AbCdEf123456{}}}).
> ----
> h4. Step 5 — Simulate strict CSP locally (optional, advanced)
> For local UI testing before backend is ready:
> ## Start dev server:
> cd dashboard && npm run dev
> ## Temporarily edit {{{}dashboard/index.html{}}}:
> <meta name="csp-nonce" content="test-local-nonce" />
> ## Add a strict CSP meta tag for testing:
> <meta http-equiv="Content-Security-Policy"
> content="default-src 'self'; script-src 'self' 'nonce-test-local-nonce';
> style-src 'self' 'nonce-test-local-nonce'; connect-src 'self'
> ws://localhost:* http://localhost:*;"/>
>
> ## Open {{http://localhost:5173/n3/}}
> ## In Console, verify:
> document.querySelector('meta[name="csp-nonce"]').content
> // → "test-local-nonce"
>
> [...document.querySelectorAll('style[data-emotion]')].every(
> s=>s.getAttribute('nonce')==='test-local-nonce'
> )
> // → true (if UI changes are working)
> Expected: Dashboard renders fully styled with zero CSP console errors.
> ----
> h3. Part 3: End-to-End Checklist
> ||#||Test||Server||UI||Pass criteria||
> |1|CSP header has nonce, no unsafe directives|curl -I|—|Header contains
> {{{}'nonce-...'{}}}, no {{'unsafe-inline'}}|
> |2|HTML meta tag populated|curl HTML|DevTools|Meta content matches header
> nonce|
> |3|Script tags have nonce|curl HTML|DevTools|{{nonce="..."}} on module
> scripts|
> |4|Emotion styles have nonce|—|DevTools|All {{style[data-emotion]}} have
> matching nonce|
> |5|Dashboard renders|—|Browser|No broken/unstyled UI|
> |6|No console CSP errors|—|Browser|Console clean on all flows|
> |7|Search works|—|Browser|Functional + styled|
> |8|Entity detail works|—|Browser|Tabs, properties render|
> |9|Login page works|curl|Browser|Backend scope — no blocked scripts|
--
This message was sent by Atlassian Jira
(v8.20.10#820010)