feat: add temporal context and contextual help
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
# Contextual Help Contract
|
||||
|
||||
GovOPlaN exposes context-sensitive help through `F1` and the titlebar help
|
||||
control. The shell resolves a stable help identity from the focused control,
|
||||
its containing surface, and the current route. The Docs module then projects
|
||||
the best visible user or administrator topic for that identity.
|
||||
|
||||
## Resolution Order
|
||||
|
||||
The WebUI resolves help in this order:
|
||||
|
||||
1. an explicit `helpContextId` or `data-help-context-id` on the focused item
|
||||
2. the focused shared control's `interfaceId`, `helpTopicId`, and label key
|
||||
3. a containing dialog, card, administration section, or page surface
|
||||
4. the current registered route, including dynamic module routes
|
||||
5. a stable route-derived fallback when no explicit identity is available
|
||||
|
||||
Focused field and action contexts retain the page context as
|
||||
`fallback_context`. This lets Docs show a field-specific topic when one exists
|
||||
and otherwise open the owning page or module documentation instead of a generic
|
||||
help page.
|
||||
|
||||
## Documentation Lookup
|
||||
|
||||
Static `DocumentationTopic` contributions announce exact contexts through
|
||||
`metadata.help_contexts`. Core publishes that catalogue with the enabled module
|
||||
manifest, allowing the shell to link directly to an exact topic when possible.
|
||||
Docs still performs the authoritative audience, permission, configured-state,
|
||||
and documentation-type filtering.
|
||||
|
||||
When there is no exact topic, Docs resolves the page fallback and then the first
|
||||
visible topic owned by the module. If Docs is unavailable, the shell opens the
|
||||
hosted documentation with the same context parameters.
|
||||
|
||||
## Authoring Controls
|
||||
|
||||
Core shared controls expose stable help metadata. Prefer these props rather
|
||||
than adding custom `F1` listeners:
|
||||
|
||||
- `interfaceId` identifies a durable UI surface or action.
|
||||
- `helpContextId` identifies a documentation context when it differs from the
|
||||
interface identity.
|
||||
- `helpTopicId` links directly to a module-owned documentation topic.
|
||||
- translated label keys provide deterministic field identities for ordinary
|
||||
`FormField`, `ToggleSwitch`, search, date/time, email, button, dialog, and card
|
||||
controls.
|
||||
|
||||
Module routes, public routes, settings sections, and administration sections
|
||||
may also declare `helpContextId` and `helpTopicId`. Each module must keep a
|
||||
static user/admin documentation baseline and should list its important route,
|
||||
workflow, setting, permission, and limitation identities in
|
||||
`metadata.help_contexts`.
|
||||
|
||||
## Boundary
|
||||
|
||||
Help identities describe presentation context; they are not authorization
|
||||
claims. Opening help never bypasses route or documentation permissions. Docs
|
||||
owns documentation projection, feature modules own their content, and Core owns
|
||||
focus capture, context resolution, and fallback routing.
|
||||
@@ -17,6 +17,8 @@ operator, and roadmap pages.
|
||||
| Action/effect automation layer | `ACTION_EFFECT_AUTOMATION_LAYER.md` | Action/effect contracts, consequence preview, runner semantics, and module boundary for automation. |
|
||||
| External references and integration maturity | `EXTERNAL_REFERENCES_AND_INTEGRATION_MATURITY.md` | Stable external identity and cumulative connector maturity; configured source authority is defined by the meta target architecture. |
|
||||
| Institutional context and governed references | `INSTITUTIONAL_CONTEXT_CONTRACT.md` | Shared temporal, actor/representation, institution, mandate, service, party, decision, evidence, legal-basis, information-governance, presentation, and geo DTO/provider contracts. |
|
||||
| Temporal data read context | `TEMPORAL_DATA_CONTEXT.md` | Valid-time and recorded-time titlebar selection, HTTP/cache contract, security boundary, and module-adoption rule. |
|
||||
| Context-sensitive F1 help | `CONTEXTUAL_HELP_CONTRACT.md` | Focus, route, module-manifest documentation contexts, Docs projection, and hosted fallback. |
|
||||
| Postbox E2EE target architecture | `POSTBOX_E2EE_ARCHITECTURE.md` | Strategic encrypted postbox/mailbox model, key ownership, role mailbox semantics, and retraction limits. |
|
||||
| Shared state, runtime coordination, and recovery | `STATE_AND_RECOVERY_CONTRACT.md` | State profiles, object storage, node registration/drain, fenced leases, migration ordering, and recovery evidence. |
|
||||
| Module lifecycle recovery | `MODULE_LIFECYCLE_RECOVERY.md` | Installer/live-graph recovery modes, deployment fence, evidence, retry blocking, and operator reconciliation. |
|
||||
|
||||
@@ -8,6 +8,9 @@ The shared contract lives in `govoplan_core.core.institutional`.
|
||||
Core owns reference shapes and provider protocols only. It does not own shared
|
||||
Mandate, Service, Party, Decision, evidence, or geography tables. Domain modules
|
||||
own persistence and authorization; optional capabilities resolve the references.
|
||||
Interactive reads use the separate platform temporal-data context documented in
|
||||
`TEMPORAL_DATA_CONTEXT.md`; it never changes current authorization or supplies
|
||||
mutation dates.
|
||||
|
||||
## Envelope
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ domain modules own their compositions.
|
||||
| Reusable credentials | Repeated administration with an adaptive create/edit dialog, optional password generator, and destructive confirmation | Secret values are write-only; generated candidates use the browser cryptographic API without a weak fallback and do not replace the field until explicitly confirmed; scope/permission blockers name the required action, responsible actor, and destination; unavailable row actions remain keyboard-explainable | `CredentialEnvelopeManager.tsx`, shared `PasswordField`, `PasswordGeneratorDialog`, `ActionBlockerHint`, `Button`, `TableActionGroup`, and `ConfirmDialog` |
|
||||
| Retention policy | Effective-policy editor with inherited source paths and typed, narrowing-only controls | Parent locks and missing write authority are explicit; the save action distinguishes locks, missing target, loading, clean draft, and active save | `RetentionPolicyManagement.tsx`, policy logic tests, `test-core-interface-patterns.mjs` |
|
||||
| Module lifecycle | Guided operator projection over durable installer-queue evidence | Preflight, handoff, progress, stale evidence, recovery, and rollback consequences remain visible | Admin module lifecycle tests and the Core installer-queue contract |
|
||||
| Shared configuration primitives | Cross-module component contract | Dialog focus, blocker structure, disabled-action focus, contextual help, unsaved changes, confirmation, loading, alerts, problem lists, and policy provenance are centralized | Core component tests and module-permutation build |
|
||||
| Shared configuration primitives | Cross-module component contract | Dialog focus, blocker structure, disabled-action focus, route/page/field/action F1 help, unsaved changes, confirmation, loading, alerts, problem lists, and policy provenance are centralized | Core component tests, `CONTEXTUAL_HELP_CONTRACT.md`, and module-permutation build |
|
||||
|
||||
## Boundary
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# Temporal Data Context
|
||||
|
||||
GovOPlaN exposes one read context for data validity and system knowledge. The
|
||||
calendar control in the authenticated titlebar applies that context to
|
||||
supported list and detail reads for the current account and tenant.
|
||||
|
||||
## Two Independent Axes
|
||||
|
||||
- **Valid time** answers when a fact applied in the represented domain.
|
||||
- **Recorded time** answers what the system had recorded by a particular
|
||||
instant.
|
||||
|
||||
The default is data valid now under the latest recorded state. `At time`
|
||||
selects a valid-time instant. `All` removes the valid-time interval filter but
|
||||
still uses the selected recorded state. The optional recorded-state cutoff can
|
||||
be combined with any valid-time mode, which keeps correction history distinct
|
||||
from changes in real-world validity.
|
||||
|
||||
An interval is half open: `valid_from <= instant < valid_to`. A revision belongs
|
||||
to a recorded-state snapshot when `recorded_at <= cutoff` and it was not
|
||||
superseded at or before that cutoff.
|
||||
|
||||
## Security And Mutation Rules
|
||||
|
||||
The temporal data context is a read projection, not an authorization context.
|
||||
Authentication, permissions, active delegations, tenant boundaries, module
|
||||
policy, and maintenance controls are always evaluated under current security
|
||||
state. A historical projection never restores an expired permission.
|
||||
|
||||
The context also does not supply mutation dates. Writes continue to target the
|
||||
current lifecycle revision and must carry their explicit valid/effective dates,
|
||||
expected revision, reason, and evidence where the owning contract requires
|
||||
them. A screen showing historical data must not silently turn a normal edit
|
||||
into a historical correction.
|
||||
|
||||
## HTTP Contract
|
||||
|
||||
Core accepts these request headers:
|
||||
|
||||
| Header | Meaning |
|
||||
| --- | --- |
|
||||
| `X-Govoplan-Validity-Mode` | `current`, `at`, or `all` |
|
||||
| `X-Govoplan-Valid-At` | Timezone-aware ISO 8601 instant required by `at` |
|
||||
| `X-Govoplan-Recorded-At` | Optional timezone-aware system-knowledge cutoff |
|
||||
|
||||
Invalid or naive timestamps fail with HTTP 400. Responses expose the resolved
|
||||
mode and evaluated instant. Conditional JSON responses vary by all three
|
||||
request headers, and the shared WebUI API client includes them in request
|
||||
deduplication and conditional-cache keys.
|
||||
|
||||
## Module Adoption
|
||||
|
||||
Revision-owning modules apply
|
||||
`govoplan_core.db.temporal.apply_temporal_revision_filter` only to read queries
|
||||
that are meant to follow the platform context. Explicit version references and
|
||||
explicit resolver `effective_at` arguments take precedence. Current-row
|
||||
lookups used for optimistic concurrency, authorization, routing, effects, or
|
||||
other mutations must remain explicit and context-independent.
|
||||
|
||||
The initial bitemporal adoption covers Decisions, Mandates, Parties, and
|
||||
Services. Their immutable revisions have indexed valid, recorded, and
|
||||
superseded timestamps. Modules with effective-dated security records or
|
||||
recorded-only revision histories require separate display-query adoption so
|
||||
the global selector cannot affect current authorization or execution.
|
||||
|
||||
The WebUI selection is stored in session storage per account and tenant. A
|
||||
change remounts the active module route so existing page loaders issue a fresh
|
||||
request. Returning both axes to their defaults removes the stored selection.
|
||||
@@ -51,10 +51,12 @@ contestability, responsibility, and traceability at the point of action.
|
||||
| UX-025 | `window.alert` and the global `alert` function are prohibited. A narrowly necessary exception requires product-owner authorization and an entry in the alert exception register before implementation. | Accepted | All WebUI code |
|
||||
| UX-026 | A table defines one stable ordered action set. A row-level unavailable action remains in its normal position and is disabled, preferably with `disabledReason`; structurally irrelevant actions are omitted for the entire table. Empty rows reserve the same slots so their Add action stays in the normal left-most action position. | Accepted | All structured tables |
|
||||
| UX-027 | The platform icon rail keeps its brand header and utility footer visible. Only the module-navigation region scrolls when installed and permitted modules exceed the available viewport height. | Accepted | Core WebUI shell |
|
||||
| UX-028 | Maintenance and offline state change the titlebar surface and repeat a quiet status label behind its controls. They must not replace, cover, or intercept the centered global-search surface; an accessible status control remains in the leading titlebar area. | Accepted | Core WebUI shell |
|
||||
| UX-028 | Maintenance and offline states use their established textual warning banners centered in the titlebar. They must not recolor the shell or add decorative status icons. Global search is a right-side command, so warnings do not replace its trigger or overlay. | Accepted | Core WebUI shell |
|
||||
| UX-029 | Recoverable page and module errors use the central compact `DismissibleAlert` presentation with an explicit recovery action where one exists. Full-height workspaces must overlay page feedback instead of allowing an alert to become a stretched workspace row. | Accepted | Core and module WebUIs |
|
||||
| UX-030 | At narrow widths, the titlebar uses separate context and command rows. Context selectors remain horizontally reachable, search retains its compact trigger, and language/help/notification/account commands remain fixed icon controls without overlap. Shared content padding contracts so domain workspaces retain usable width. | Accepted | Core WebUI shell and all module workspaces |
|
||||
| UX-031 | Public controls and extension contributions use stable, module-namespaced interface identities. Shared controls expose `interfaceId` and `helpTopicId`; generated source anchors are inventory evidence, not a substitute for an explicit ID when documentation, policy, or automation refers to the control. | Accepted | Core and module WebUIs |
|
||||
| UX-032 | `F1` resolves help from the focused field or action, then its dialog/section/page and registered route. Focused contexts retain the page fallback; Docs applies audience and permission filtering and falls back to visible module documentation. | Accepted | Core shell, Docs, and all module WebUIs |
|
||||
| UX-033 | Global search is the left-most titlebar command, immediately before language selection. Its icon, `F3`, and `Ctrl`/`Cmd`+`K` all open the same permission-aware search overlay; the titlebar does not reserve a persistent query field. | Accepted | Core shell and Search WebUI |
|
||||
|
||||
## Confirmed Implementation Decisions
|
||||
|
||||
|
||||
Reference in New Issue
Block a user