Commit 1b9d026
authored
feat(context-navigation): add plugin package, dev portal integration, and plugin docs (#4751)
* feat(context-navigation): add context navigation plugin package
Introduce a new plugin that manages bidirectional synchronization
between the browser URL and the selected context (e.g. facility,
project).
Supports three routing strategies:
- 'path': context ID embedded in the URL path segment
- 'query': context ID as a query parameter (?contextId=...)
- 'custom': consumer-provided adapter for non-standard URL layouts
Key capabilities:
- URL guard that intercepts navigation to resolve context from URLs
- Reconciler that updates the URL when context changes programmatically
- App-first and context-first source factories for initial resolution
- Active-app navigation event stream for cross-app context handoff
- Legacy app path normalization for backward compatibility
Includes full test coverage for plugin lifecycle, guard handlers,
reconciliation logic, and navigation event operators.
* feat(context): add routing strategy and navigation fixes
Extend the context module with a routingStrategy configuration option
that controls how context identity is represented in URLs ('path' or
'query'). This is the foundation the context-navigation plugin reads
to decide which adapter to use.
Context module changes:
- Add routingStrategy to ContextModuleConfig and configurator
- Add setRoutingStrategy() to ContextConfigBuilder
- Update resolveContextFromPath with custom matcher support and TSDoc
- Simplify resolveInitialContext to only resolve from parent context
(URL-based resolution is now handled by the plugin)
- Expose routingStrategy on ContextProvider and IContextProvider
- Add routingStrategy as third argument to generatePathFromContext
- Add migration guide for routing strategy adoption
Navigation module changes:
- Stop stripping trailing slashes in normalizePathname
- Fix basename boundary check in _isWithinBasenameScope to prevent
false positives from overlapping app name prefixes
- Fall back to '/' in _localizePath when basename-stripped path is empty
* feat(dev-portal): integrate context navigation plugin
Wire up the context-navigation plugin in the dev portal so that apps
running in the development shell get automatic URL-to-context
synchronization matching production behavior.
Dev portal changes:
- Enable context-navigation plugin with setPortalName, setDebug,
and setUrlGuard in dev portal config
- Enable context module with path generator and extractor using
plugin utility functions (buildContextUrlForStrategy,
resolveContextIdFromUrl)
- Set explicit 'path' routing strategy
- Delete useAppContextNavigation hook (replaced by plugin)
- Remove useAppContextNavigation() call from Router component
- Update README to document context navigation plugin integration
Cookbook changes:
- Add explicit setRoutingStrategy('path') to context-using cookbook
configs (app-react-context, app-react-bookmark,
app-react-bookmark-advanced, app-react-context-custom-error,
portal-analytics)
* docs: add plugin documentation, migration guides, and changesets
VuePress documentation:
- Add top-level plugins section with overview of plugin vs module
intent and the context-navigation plugin README
- Add context routing strategy migration guide under modules/context
- Update sidebar and theme config for new plugin section
Changesets:
- plugin-context-navigation: initial release (minor)
- module-context: routing strategy addition (minor)
- module-navigation: trailing-slash and basename fix (patch)
- dev-portal: context navigation integration (patch)
Also updates pnpm-lock.yaml for new plugin package dependency.
* docs: improve context routing documentation and fix TSDoc accuracy
* fix(changeset): correct context module changeset to reflect actual changes vs main
The previous changeset described removing routingStrategy from the context
module, but that feature never existed on main. The actual change is moving
URL-based initial context resolution from the context module to the
context-navigation plugin.
Changes:
- Downgrade from major to patch (no breaking changes vs main)
- Accurately describe the URL resolution responsibility shift
- Remove references to routingStrategy removal (never existed on main)
- Keep migration guidance focused on plugin enablement
* fix(context-provider): suppress TypeScript errors for future signature updates
* fix(navigation): normalize basename to treat '/' as no-basename and fix scope checks
* fix(context-navigation): force replace:true on app switch and URL drift correction to prevent back-navigation traps
* fix(navigation): prevent ReDoS vulnerability in pathname normalization
Replace regex-based slash collapsing with iterative approach to eliminate
potential Regular Expression Denial of Service attack when processing
user-controlled basename values with pathological input.
The normalizePathname function now guarantees O(n) linear time complexity
instead of using /\/+/g regex pattern that could be exploited with
thousands of consecutive slashes.
Adds ReDoS protection test to verify performance with pathological input.
Resolves CodeQL security alert: Polynomial regular expression used on
uncontrolled data (High severity)
Related: #4751
* fix(context-navigation): clear hash fragment on context changes
Hash fragments are intentionally cleared when context changes to prevent
inconsistent app state. When a context change resets the app to its root
view, preserving the hash would leave anchors pointing to sections that
may not exist in the new context.
This matches the existing behavior for sub-routes (intentionally dropped)
and maintains consistency across all three adapters (path, query, custom).
Adds test to verify hash is cleared on context change.
Addresses PR review feedback in #4751
* fix(navigation): eliminate remaining ReDoS vulnerability in trailing slash removal
Replace regex-based trailing slash removal (.replace(/\/+$/, '')) with
iterative stripTrailingSlashes() function to prevent ReDoS attacks.
The /\/+$/ pattern can cause exponential backtracking when processing
basenames with thousands of trailing slashes. The new stripTrailingSlashes
function guarantees O(n) linear time by scanning backwards from the end.
Added test verifying performance with 10k trailing slashes (< 100ms).
This completes the ReDoS vulnerability remediation - both consecutive
slash patterns are now safe:
- normalizePathname: O(n) forward scan (commit ee14d80)
- stripTrailingSlashes: O(n) backward scan (this commit)
Addresses CodeQL alert: Polynomial regular expression used on uncontrolled data
* fix(navigation): refactor pathname normalization functions to improve performance and avoid ReDoS vulnerabilities
* refactor: improve readability by adding braces to conditional statements and using array for path construction
* chore: remove unnecessary blank line in handleReplaceModeGuard function1 parent c4b4ab1 commit 1b9d026
87 files changed
Lines changed: 6718 additions & 1163 deletions
File tree
- .changeset
- packages
- dev-portal
- src
- modules
- app/src
- context
- src
- utils
- vue-press/src
- .vuepress
- plugins
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 7 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
Lines changed: 16 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
Lines changed: 9 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
Lines changed: 19 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
16 | | - | |
| 16 | + | |
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| |||
82 | 82 | | |
83 | 83 | | |
84 | 84 | | |
85 | | - | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
86 | 92 | | |
87 | 93 | | |
88 | 94 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
| 43 | + | |
43 | 44 | | |
44 | 45 | | |
45 | 46 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
16 | | - | |
| 16 | + | |
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| |||
94 | 94 | | |
95 | 95 | | |
96 | 96 | | |
97 | | - | |
| 97 | + | |
| 98 | + | |
98 | 99 | | |
99 | 100 | | |
100 | 101 | | |
101 | 102 | | |
102 | | - | |
| 103 | + | |
103 | 104 | | |
104 | 105 | | |
105 | 106 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| 37 | + | |
37 | 38 | | |
38 | 39 | | |
39 | 40 | | |
| |||
53 | 54 | | |
54 | 55 | | |
55 | 56 | | |
| 57 | + | |
56 | 58 | | |
57 | 59 | | |
58 | 60 | | |
59 | 61 | | |
60 | 62 | | |
61 | 63 | | |
| 64 | + | |
62 | 65 | | |
63 | 66 | | |
64 | 67 | | |
| |||
72 | 75 | | |
73 | 76 | | |
74 | 77 | | |
| 78 | + | |
75 | 79 | | |
76 | 80 | | |
77 | 81 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
9 | 8 | | |
10 | 9 | | |
11 | 10 | | |
| |||
76 | 75 | | |
77 | 76 | | |
78 | 77 | | |
79 | | - | |
80 | | - | |
| 78 | + | |
| 79 | + | |
81 | 80 | | |
82 | 81 | | |
83 | | - | |
84 | | - | |
85 | 82 | | |
86 | 83 | | |
0 commit comments