Track catalog transitions - #173
Conversation
Create SafeUrlValidatorService for http/https validation. Create DomainOriginVerificationService for strict iframe networking validation.
Wire bypassSecurityTrustResourceUrl inside rendered-frame.ts through the rigorous URL validator. Swap the check in preview-bridge.ts for the strict origin verification. Fix LLM concurrency in ChatCoordinator submitPrompt. Fix Monaco model.dispose() in a2ui-composer-monaco-editor. Inject takeUntilDestroyed in api-key-selector.ts and renderer-selector.ts.
Delete debug/mock-rules/ entirely. Rip out console.error patch hacks from ChatCoordinator. Delete obsolete storage key ACTIVE_DRAFT.
…hot Capture and IDB Base
…ks into decoupled targets accurately abandoning monolithic arrays globally
…mentations and un-deferred webrtc layout code gracefully
…ngestion - Implement TrackEventDirective applying declarative tracking boundaries natively. - Construct FileIngestionService strictly leveraging @angular/cdk/clipboard utilities. - Construct ShareService cleanly encapsulating clipboard interactions.
- Sweep all active standalone UI components throughout the app, converting default ChangeDetection behavior to ChangeDetectionStrategy.OnPush. - Strip FileReader native accesses from ChatPanel into the FileIngestionService. - Swap template tracking to the directive.
- Rip out the legacy shareDesign() bloated component implementation comprehensively. - Delete deprecated inner test asserts and old inline code.
When a design link is shared and loaded, cleanSharedA2uiUrl removes the 'a2ui', 'renderer', and 'rendererId' parameters from the window hash and search parameters using history.replaceState so they do not linger in the address bar. Additionally, update StartupResolution to map queryRendererUrl to its corresponding static or custom renderer configuration and persist allowed unknown URLs into LocalStorage. Update Settings view to default to the active renderer selection instead of an unselected state. Include rendererId alongside renderer in share URL hashes.
Update tryParseJsonArray in shell utils/json.ts to parse:
- Standard JSON arrays ([...])
- Single JSON objects ({...} -> [obj])
- JSON Lines ({...}\n{...} -> [obj1, obj2, ...])
Update RawFrame to use tryParseJsonArray when parsing layout JSON.
Update ChatCleaner to validate layout snapshots using isLayoutArray.
Add unit tests covering JSON Lines, single objects, and edge cases.
Refactor StateSync to treat A2UI_CATALOG capability announcements as passive handshakes rather than destructive transition triggers: - Track isDraftModified to protect sidecar injected drafts, transcript replays, and user edits from asynchronous handshake clobbering. - Handle renderer switches via selectedRendererId$ by resetting the modification lock to synchronize new default renderer templates. - Filter catalog streams safely to support custom renderers without formal catalog IDs. - Decouple getInitialDraft from sharedA2uiPayload to ensure clean resets in shared URL sessions.
⚡ A2UI Composer PR PreviewYour automated preview is successfully live (commit
|
There was a problem hiding this comment.
Code Review
This pull request refactors the chat and workspace shell by modularizing payload parsing, file ingestion, error formatting, screenshot capture, and sharing services, while also removing the deprecated mock rules debug panel. The review feedback identifies a critical bug in the new sanitizeValue function where rules and mock* properties are not filtered out, a recommendation to harden tryParseJsonArray against nullish inputs, and the usage of the deprecated substr method in the Monaco editor component.
| for (const [key, propVal] of Object.entries(obj)) { | ||
| cleaned[key] = sanitizeValue(propVal); | ||
| } |
There was a problem hiding this comment.
The new implementation of sanitizeValue completely omitted the filtering logic for rules and mock* properties. This causes mock configurations and rules to leak into the production payload, which can lead to validation failures or security/privacy issues. Additionally, the unit test removes mock* and rules properties in a2ui-payload-parser.spec.ts is passing because it only asserts that valid properties are preserved, but fails to assert that mock/rules properties are actually removed.
for (const [key, propVal] of Object.entries(obj)) {
if (key === 'rules' || /^mock/i.test(key)) {
continue;
}
cleaned[key] = sanitizeValue(propVal);
}| export function tryParseJsonArray(content: string): unknown[] | null { | ||
| const trimmed = content.trim(); | ||
| if (trimmed.length === 0) { | ||
| return null; | ||
| } |
There was a problem hiding this comment.
Per the general rules, string processing utility methods should be hardened with guard clauses to safely handle nullish or undefined inputs by returning safe defaults, and corresponding unit tests should be added to verify resilience against nullish values. Please add a guard clause to handle nullish/undefined content inputs.
| export function tryParseJsonArray(content: string): unknown[] | null { | |
| const trimmed = content.trim(); | |
| if (trimmed.length === 0) { | |
| return null; | |
| } | |
| export function tryParseJsonArray(content: string | null | undefined): unknown[] | null { | |
| if (!content) { | |
| return null; | |
| } | |
| const trimmed = content.trim(); |
References
- Harden string processing utility methods with guard clauses to safely handle nullish or undefined inputs by returning safe defaults, and ensure corresponding unit tests are added to verify resilience against nullish values.
| styleUrl: './monaco-editor.scss', | ||
| }) | ||
| export class MonacoEditor { | ||
| private readonly layoutModelUriStr = `a2ui://layout-${Math.random().toString(36).substr(2, 9)}.json`; |
There was a problem hiding this comment.
String.prototype.substr is deprecated. Please use slice or substring instead to ensure long-term compatibility and adhere to modern JavaScript standards.
| private readonly layoutModelUriStr = `a2ui://layout-${Math.random().toString(36).substr(2, 9)}.json`; | |
| private readonly layoutModelUriStr = `a2ui://layout-${Math.random().toString(36).slice(2, 11)}.json`; |
Description
Passive Handshake Model & User Draft Protection
Pre-launch Checklist
If you need help, consider asking for advice on the [discussion board].