@almadar/std 16.234.0 → 16.236.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/behaviors/behaviors-registry.json +4402 -1898
- package/behaviors/lolo/infra/atoms/std-approval-gate.lolo +25 -41
- package/behaviors/lolo/infra/atoms/std-audit-capture.lolo +0 -5
- package/behaviors/lolo/infra/atoms/std-cache-aside.lolo +0 -24
- package/behaviors/lolo/infra/atoms/std-circuit-breaker.lolo +1 -17
- package/behaviors/lolo/infra/atoms/std-data-erasure.lolo +17 -24
- package/behaviors/lolo/infra/atoms/std-data-import.lolo +8 -11
- package/behaviors/lolo/infra/atoms/std-game-clock.lolo +2 -0
- package/behaviors/lolo/infra/atoms/std-knowledge-loop.lolo +0 -5
- package/behaviors/lolo/infra/atoms/std-lifecycle.lolo +3 -1
- package/behaviors/lolo/infra/atoms/std-mod-queue.lolo +40 -18
- package/behaviors/lolo/infra/atoms/std-notification-preferences.lolo +20 -11
- package/behaviors/lolo/infra/atoms/std-notify-on-event.lolo +0 -5
- package/behaviors/lolo/infra/atoms/std-permission-matrix.lolo +23 -11
- package/behaviors/lolo/infra/atoms/std-rate-limiter.lolo +84 -22
- package/behaviors/lolo/infra/atoms/std-status-lifecycle.lolo +1 -6
- package/behaviors/lolo/ml/atoms/std-graph-builder.lolo +3 -1
- package/behaviors/lolo/ml/atoms/std-ml-classify.lolo +0 -4
- package/behaviors/lolo/ml/atoms/std-ml-similarity.lolo +0 -4
- package/behaviors/lolo/ui/avl/atoms/ui-avl-state-machine.lolo +12 -0
- package/behaviors/lolo/ui/core/atoms/std-app-layout.lolo +55 -9
- package/behaviors/lolo/ui/core/atoms/std-app-search.lolo +6 -2
- package/behaviors/lolo/ui/core/atoms/std-billable-hour.lolo +19 -14
- package/behaviors/lolo/ui/core/atoms/std-board.lolo +77 -27
- package/behaviors/lolo/ui/core/atoms/std-browse.lolo +44 -28
- package/behaviors/lolo/ui/core/atoms/std-calendar.lolo +7 -3
- package/behaviors/lolo/ui/core/atoms/std-esign-flow.lolo +25 -13
- package/behaviors/lolo/ui/core/atoms/std-esign-request.lolo +5 -0
- package/behaviors/lolo/ui/core/atoms/std-event-log.lolo +0 -5
- package/behaviors/lolo/ui/core/atoms/std-export.lolo +0 -10
- package/behaviors/lolo/ui/core/atoms/std-file-store.lolo +7 -3
- package/behaviors/lolo/ui/core/atoms/std-form-advanced.lolo +1 -6
- package/behaviors/lolo/ui/core/atoms/std-geosearch.lolo +1 -0
- package/behaviors/lolo/ui/core/atoms/std-graphs.lolo +20 -4
- package/behaviors/lolo/ui/core/atoms/std-import.lolo +0 -5
- package/behaviors/lolo/ui/core/atoms/std-list.lolo +46 -32
- package/behaviors/lolo/ui/core/atoms/std-modal-editor.lolo +2 -2
- package/behaviors/lolo/ui/core/atoms/std-rating-review.lolo +12 -13
- package/behaviors/lolo/ui/core/atoms/std-record-detail.lolo +16 -12
- package/behaviors/lolo/ui/core/atoms/std-recurrence.lolo +10 -1
- package/behaviors/lolo/ui/core/atoms/std-role-gate.lolo +39 -0
- package/behaviors/lolo/ui/core/atoms/std-saved-search.lolo +78 -16
- package/behaviors/lolo/ui/core/atoms/std-selection.lolo +15 -10
- package/behaviors/lolo/ui/core/atoms/std-stats.lolo +5 -5
- package/behaviors/lolo/ui/core/atoms/std-tag-taxonomy.lolo +3 -0
- package/behaviors/lolo/ui/core/atoms/std-thread.lolo +41 -73
- package/behaviors/lolo/ui/core/atoms/std-version-history.lolo +20 -11
- package/behaviors/lolo/ui/core/atoms/std-vote.lolo +0 -4
- package/behaviors/lolo/ui/core/atoms/std-wizard.lolo +3 -3
- package/behaviors/lolo/ui/core/atoms/ui-presence.lolo +21 -0
- package/behaviors/lolo/ui/core/molecules/ui-breadcrumb.lolo +6 -1
- package/behaviors/lolo/ui/core/molecules/ui-chart.lolo +11 -1
- package/behaviors/lolo/ui/core/molecules/ui-code-block.lolo +13 -8
- package/behaviors/lolo/ui/core/molecules/ui-command-palette.lolo +7 -2
- package/behaviors/lolo/ui/core/molecules/ui-commit-row.lolo +2 -2
- package/behaviors/lolo/ui/core/molecules/ui-confirm-dialog.lolo +8 -0
- package/behaviors/lolo/ui/core/molecules/ui-data-grid.lolo +41 -3
- package/behaviors/lolo/ui/core/molecules/ui-data-list.lolo +41 -3
- package/behaviors/lolo/ui/core/molecules/ui-document-details.lolo +30 -9
- package/behaviors/lolo/ui/core/molecules/ui-document-panel.lolo +8 -3
- package/behaviors/lolo/ui/core/molecules/ui-document-viewer.lolo +6 -1
- package/behaviors/lolo/ui/core/molecules/ui-drawer.lolo +13 -0
- package/behaviors/lolo/ui/core/molecules/ui-floating-action-button.lolo +6 -1
- package/behaviors/lolo/ui/core/molecules/ui-floating-toolbar.lolo +6 -1
- package/behaviors/lolo/ui/core/molecules/ui-form-actions.lolo +6 -1
- package/behaviors/lolo/ui/core/molecules/ui-graph-canvas.lolo +6 -1
- package/behaviors/lolo/ui/core/molecules/ui-menu.lolo +6 -1
- package/behaviors/lolo/ui/core/molecules/ui-meter.lolo +6 -1
- package/behaviors/lolo/ui/core/molecules/ui-modal.lolo +5 -0
- package/behaviors/lolo/ui/core/molecules/ui-page-header.lolo +11 -1
- package/behaviors/lolo/ui/core/molecules/ui-page-transition.lolo +1 -1
- package/behaviors/lolo/ui/core/molecules/ui-swipeable-row.lolo +44 -15
- package/behaviors/lolo/ui/core/molecules/ui-table-view.lolo +41 -3
- package/behaviors/lolo/ui/core/molecules/ui-tabs.lolo +8 -2
- package/behaviors/lolo/ui/core/organisms/ui-detail-panel.lolo +66 -12
- package/behaviors/lolo/ui/core/organisms/ui-entity-cards.lolo +9 -3
- package/behaviors/lolo/ui/core/organisms/ui-entity-list.lolo +9 -3
- package/behaviors/lolo/ui/core/organisms/ui-entity-table.lolo +18 -9
- package/behaviors/lolo/ui/core/organisms/ui-form-section.lolo +55 -10
- package/behaviors/lolo/ui/core/organisms/ui-form.lolo +55 -10
- package/behaviors/lolo/ui/core/organisms/ui-media-gallery.lolo +8 -3
- package/behaviors/lolo/ui/core/organisms/ui-state-machine-view.lolo +12 -0
- package/behaviors/lolo/ui/core/organisms/ui-timeline.lolo +8 -3
- package/behaviors/lolo/ui/core/templates/ui-counter-template.lolo +2 -44
- package/behaviors/lolo/ui/core/templates/ui-dashboard-layout.lolo +6 -1
- package/behaviors/lolo/ui/core/templates/ui-generic-app-template.lolo +2 -37
- package/behaviors/lolo/ui/game/atoms/ui-game-menu.lolo +8 -2
- package/behaviors/lolo/ui/game/organisms/std-arcade-board-3d.lolo +2 -2
- package/behaviors/lolo/ui/game/organisms/std-crew-board-2d.lolo +0 -4
- package/behaviors/lolo/ui/game/organisms/std-platformer-puzzle.lolo +2 -66
- package/behaviors/lolo/ui/game/organisms/std-tactics-board-2d.lolo +0 -4
- package/behaviors/lolo/ui/game/organisms/std-worldmap-board-2d.lolo +0 -4
- package/behaviors/lolo/ui/learning/atoms/std-learn-stepper.lolo +6 -6
- package/behaviors/lolo-behavior-contracts.json +1 -1
- package/behaviors/registry/factory-signatures.json +1 -1
- package/behaviors/registry/infra/atoms/std-approval-gate.orb +124 -67
- package/behaviors/registry/infra/atoms/std-audit-capture.orb +0 -8
- package/behaviors/registry/infra/atoms/std-cache-aside.orb +0 -84
- package/behaviors/registry/infra/atoms/std-circuit-breaker.orb +1 -44
- package/behaviors/registry/infra/atoms/std-data-erasure.orb +124 -55
- package/behaviors/registry/infra/atoms/std-data-import.orb +12 -11
- package/behaviors/registry/infra/atoms/std-game-clock.orb +31 -0
- package/behaviors/registry/infra/atoms/std-knowledge-loop.orb +0 -57
- package/behaviors/registry/infra/atoms/std-lifecycle.orb +43 -0
- package/behaviors/registry/infra/atoms/std-mod-queue.orb +379 -103
- package/behaviors/registry/infra/atoms/std-notification-preferences.orb +126 -12
- package/behaviors/registry/infra/atoms/std-notify-on-event.orb +0 -11
- package/behaviors/registry/infra/atoms/std-permission-matrix.orb +128 -12
- package/behaviors/registry/infra/atoms/std-rate-limiter.orb +287 -72
- package/behaviors/registry/infra/atoms/std-status-lifecycle.orb +5 -8
- package/behaviors/registry/ml/atoms/std-graph-builder.orb +11 -0
- package/behaviors/registry/ml/atoms/std-ml-classify.orb +0 -7
- package/behaviors/registry/ml/atoms/std-ml-similarity.orb +0 -7
- package/behaviors/registry/ui/avl/atoms/ui-avl-state-machine.orb +82 -0
- package/behaviors/registry/ui/core/atoms/std-app-layout.orb +417 -9
- package/behaviors/registry/ui/core/atoms/std-app-search.orb +53 -1
- package/behaviors/registry/ui/core/atoms/std-billable-hour.orb +209 -19
- package/behaviors/registry/ui/core/atoms/std-board.orb +242 -61
- package/behaviors/registry/ui/core/atoms/std-browse.orb +295 -41
- package/behaviors/registry/ui/core/atoms/std-calendar.orb +96 -2
- package/behaviors/registry/ui/core/atoms/std-esign-flow.orb +122 -15
- package/behaviors/registry/ui/core/atoms/std-esign-request.orb +11 -0
- package/behaviors/registry/ui/core/atoms/std-event-log.orb +0 -8
- package/behaviors/registry/ui/core/atoms/std-export.orb +0 -16
- package/behaviors/registry/ui/core/atoms/std-file-store.orb +109 -2
- package/behaviors/registry/ui/core/atoms/std-form-advanced.orb +1 -43
- package/behaviors/registry/ui/core/atoms/std-geosearch.orb +5 -0
- package/behaviors/registry/ui/core/atoms/std-graphs.orb +173 -66
- package/behaviors/registry/ui/core/atoms/std-import.orb +0 -8
- package/behaviors/registry/ui/core/atoms/std-list.orb +226 -34
- package/behaviors/registry/ui/core/atoms/std-modal-editor.orb +10 -1
- package/behaviors/registry/ui/core/atoms/std-rating-review.orb +37 -19
- package/behaviors/registry/ui/core/atoms/std-record-detail.orb +204 -11
- package/behaviors/registry/ui/core/atoms/std-recurrence.orb +89 -4
- package/behaviors/registry/ui/core/atoms/std-role-gate.orb +217 -0
- package/behaviors/registry/ui/core/atoms/std-saved-search.orb +419 -19
- package/behaviors/registry/ui/core/atoms/std-selection.orb +140 -10
- package/behaviors/registry/ui/core/atoms/std-stats.orb +73 -1
- package/behaviors/registry/ui/core/atoms/std-tag-taxonomy.orb +3 -0
- package/behaviors/registry/ui/core/atoms/std-thread.orb +190 -115
- package/behaviors/registry/ui/core/atoms/std-version-history.orb +127 -13
- package/behaviors/registry/ui/core/atoms/std-vote.orb +0 -9
- package/behaviors/registry/ui/core/atoms/std-wizard.orb +33 -3
- package/behaviors/registry/ui/core/atoms/ui-presence.orb +59 -0
- package/behaviors/registry/ui/core/molecules/ui-breadcrumb.orb +53 -1
- package/behaviors/registry/ui/core/molecules/ui-chart.orb +68 -1
- package/behaviors/registry/ui/core/molecules/ui-code-block.orb +291 -8
- package/behaviors/registry/ui/core/molecules/ui-command-palette.orb +87 -2
- package/behaviors/registry/ui/core/molecules/ui-commit-row.orb +3 -2
- package/behaviors/registry/ui/core/molecules/ui-confirm-dialog.orb +32 -0
- package/behaviors/registry/ui/core/molecules/ui-data-grid.orb +189 -3
- package/behaviors/registry/ui/core/molecules/ui-data-list.orb +189 -3
- package/behaviors/registry/ui/core/molecules/ui-document-details.orb +81 -24
- package/behaviors/registry/ui/core/molecules/ui-document-panel.orb +121 -3
- package/behaviors/registry/ui/core/molecules/ui-document-viewer.orb +53 -1
- package/behaviors/registry/ui/core/molecules/ui-drawer.orb +40 -0
- package/behaviors/registry/ui/core/molecules/ui-floating-action-button.orb +53 -1
- package/behaviors/registry/ui/core/molecules/ui-floating-toolbar.orb +53 -1
- package/behaviors/registry/ui/core/molecules/ui-form-actions.orb +53 -1
- package/behaviors/registry/ui/core/molecules/ui-graph-canvas.orb +53 -1
- package/behaviors/registry/ui/core/molecules/ui-menu.orb +57 -1
- package/behaviors/registry/ui/core/molecules/ui-meter.orb +53 -1
- package/behaviors/registry/ui/core/molecules/ui-modal.orb +8 -0
- package/behaviors/registry/ui/core/molecules/ui-page-header.orb +60 -1
- package/behaviors/registry/ui/core/molecules/ui-page-transition.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-swipeable-row.orb +393 -23
- package/behaviors/registry/ui/core/molecules/ui-table-view.orb +189 -3
- package/behaviors/registry/ui/core/molecules/ui-tabs.orb +99 -2
- package/behaviors/registry/ui/core/organisms/ui-detail-panel.orb +282 -20
- package/behaviors/registry/ui/core/organisms/ui-entity-cards.orb +130 -3
- package/behaviors/registry/ui/core/organisms/ui-entity-list.orb +130 -3
- package/behaviors/registry/ui/core/organisms/ui-entity-table.orb +367 -9
- package/behaviors/registry/ui/core/organisms/ui-form-section.orb +104 -13
- package/behaviors/registry/ui/core/organisms/ui-form.orb +104 -13
- package/behaviors/registry/ui/core/organisms/ui-media-gallery.orb +121 -3
- package/behaviors/registry/ui/core/organisms/ui-state-machine-view.orb +82 -0
- package/behaviors/registry/ui/core/organisms/ui-timeline.orb +121 -3
- package/behaviors/registry/ui/core/templates/ui-counter-template.orb +1 -172
- package/behaviors/registry/ui/core/templates/ui-dashboard-layout.orb +53 -1
- package/behaviors/registry/ui/core/templates/ui-generic-app-template.orb +1 -116
- package/behaviors/registry/ui/game/atoms/ui-game-menu.orb +99 -2
- package/behaviors/registry/ui/game/organisms/std-arcade-board-3d.orb +10 -0
- package/behaviors/registry/ui/game/organisms/std-crew-board-2d.orb +0 -7
- package/behaviors/registry/ui/game/organisms/std-platformer-puzzle.orb +1 -807
- package/behaviors/registry/ui/game/organisms/std-tactics-board-2d.orb +0 -7
- package/behaviors/registry/ui/game/organisms/std-worldmap-board-2d.orb +0 -7
- package/behaviors/registry/ui/learning/atoms/std-learn-stepper.orb +6 -0
- package/canonical-operators.json +18 -1
- package/dist/behaviors/exports-reader.js +7662 -3762
- package/dist/behaviors/functions/index.d.ts +309 -104
- package/dist/behaviors/functions/index.js +7651 -3762
- package/dist/behaviors/index.d.ts +1 -1
- package/dist/behaviors/index.js +7663 -3763
- package/dist/behaviors/query.js +7662 -3762
- package/dist/behaviors-embeddings.hash.json +3 -3
- package/dist/behaviors-embeddings.json +35 -27
- package/dist/behaviors-registry.json +4402 -1898
- package/dist/index.d.ts +3 -3
- package/dist/index.js +7697 -3763
- package/dist/knob-embeddings.hash.json +3 -3
- package/dist/knob-embeddings.json +612 -352
- package/dist/modules/anim.d.ts +1 -1
- package/dist/modules/array.d.ts +1 -1
- package/dist/modules/array.js +15 -0
- package/dist/modules/async.d.ts +1 -1
- package/dist/modules/async.js +9 -0
- package/dist/modules/behavior.d.ts +1 -1
- package/dist/modules/browser.d.ts +1 -1
- package/dist/modules/composition.d.ts +1 -1
- package/dist/modules/contract.d.ts +1 -1
- package/dist/modules/core.d.ts +1 -1
- package/dist/modules/core.js +10 -0
- package/dist/modules/data.d.ts +1 -1
- package/dist/modules/ease.d.ts +1 -1
- package/dist/modules/format.d.ts +1 -1
- package/dist/modules/geo.d.ts +1 -1
- package/dist/modules/graph.d.ts +1 -1
- package/dist/modules/grid.d.ts +1 -1
- package/dist/modules/index.d.ts +1 -1
- package/dist/modules/index.js +34 -0
- package/dist/modules/integration.d.ts +1 -1
- package/dist/modules/json.d.ts +1 -1
- package/dist/modules/llm.d.ts +1 -1
- package/dist/modules/math.d.ts +1 -1
- package/dist/modules/memory.d.ts +1 -1
- package/dist/modules/nn.d.ts +1 -1
- package/dist/modules/noise.d.ts +1 -1
- package/dist/modules/object.d.ts +1 -1
- package/dist/modules/os.d.ts +1 -1
- package/dist/modules/path.d.ts +1 -1
- package/dist/modules/prob.d.ts +1 -1
- package/dist/modules/session.d.ts +1 -1
- package/dist/modules/str.d.ts +1 -1
- package/dist/modules/tensor.d.ts +1 -1
- package/dist/modules/time.d.ts +1 -1
- package/dist/modules/trace.d.ts +1 -1
- package/dist/modules/train.d.ts +1 -1
- package/dist/modules/validate.d.ts +1 -1
- package/dist/modules/vector.d.ts +1 -1
- package/dist/modules/workspace.d.ts +1 -1
- package/dist/registry/factory-signatures.json +1 -1
- package/dist/registry.d.ts +5 -2
- package/dist/registry.js +55 -1
- package/dist/{types-DwAW4Nni.d.ts → types-DLx38UFZ.d.ts} +31 -4
- package/package.json +2 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
app std-approval-gate "1.1.0"
|
|
2
2
|
"std-approval-gate — generic approval gate / approver workflow. Use when a user voices that an action must be reviewed, approved, signed off, or authorized by a privileged role before it proceeds (admin approval, supervisor sign-off, manager approval, gatekeeper review, editor approval, senior editor approval, reviewer approval, publishing approval, draft approval, content review, submit drafts then editors review and approve or reject, needs approval before going live, requires sign-off before publish). Persists ApprovalRequest rows + surfaces the PENDING ones in a review queue showing what is being approved and who asked, with Approve / Deny actions — Deny captures a written reason. approverRoles is ENFORCED by the review transitions themselves: an APPROVE/DENY from a viewer whose role is not listed does not fire. blockSelfApproval additionally stops a reviewer approving their own request (four-eyes) — DENY stays allowed as self-withdrawal. On approval emits ApprovalGranted; on denial emits ApprovalDenied (with the reason). Hosts that replay the gated action MUST route a failed replay back via APPROVAL_REPLAY_FAILED so the request reopens instead of being silently consumed. Compose onto any orbital whose action you want to gate: the target orbital emits an external event, an ApprovalRequest row is created (stamp subjectLabel/subjectId/requestedBy so reviewers see what they are judging), and downstream effects wait on ApprovalGranted. Differs from std-mod-queue, which is content-moderation-specific."
|
|
3
|
+
type ItemAction = { label : string!, event : event, variant : string, icon : string, roles : [string], when : SExpr }
|
|
3
4
|
orbital ApprovalGateOrbital {
|
|
4
5
|
uses Spinner from "std/behaviors/ui-spinner"
|
|
5
6
|
uses Typography from "std/behaviors/ui-typography"
|
|
@@ -192,22 +193,7 @@ orbital ApprovalGateOrbital {
|
|
|
192
193
|
variant: caption
|
|
193
194
|
}]
|
|
194
195
|
gap: sm
|
|
195
|
-
itemActions: [
|
|
196
|
-
event: OPEN_SUBJECT
|
|
197
|
-
icon: eye
|
|
198
|
-
label: View
|
|
199
|
-
variant: ghost
|
|
200
|
-
}, {
|
|
201
|
-
event: APPROVE
|
|
202
|
-
icon: check
|
|
203
|
-
label: Approve
|
|
204
|
-
variant: primary
|
|
205
|
-
}, {
|
|
206
|
-
event: DENY
|
|
207
|
-
icon: x
|
|
208
|
-
label: Deny
|
|
209
|
-
variant: danger
|
|
210
|
-
}]
|
|
196
|
+
itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
|
|
211
197
|
look: @config.tableLook
|
|
212
198
|
type: data-grid
|
|
213
199
|
}]
|
|
@@ -412,7 +398,6 @@ orbital ApprovalGateOrbital {
|
|
|
412
398
|
}
|
|
413
399
|
|
|
414
400
|
listens {
|
|
415
|
-
CloseButton.CLOSE -> CLOSE
|
|
416
401
|
OPEN
|
|
417
402
|
@description "Summons the review queue (host nav/affordance requests it)."
|
|
418
403
|
@synonyms "open, show, review, view queue, open approvals"
|
|
@@ -502,30 +487,6 @@ orbital ApprovalGateOrbital {
|
|
|
502
487
|
@description "When on, a reviewer cannot APPROVE a request they submitted themselves (requestedBy = the viewer's id) — enforced by the APPROVE transition guard, from the button or from the bus. Requires hosts to stamp requestedBy at request creation. DENY stays allowed on your own request (denying your own request withdraws it). Off by default."
|
|
503
488
|
@synonyms "self approval, self-approval, four eyes, four-eyes, separation of duties, cannot approve own, no self sign-off, dual control"
|
|
504
489
|
@tier "policy"
|
|
505
|
-
threshold : number = 0
|
|
506
|
-
@label "Auto-approve below this value"
|
|
507
|
-
@description "Requests whose gated value is below this threshold are auto-approved. v1.0 declarative only."
|
|
508
|
-
@synonyms "auto approve amount, skip review under, threshold, limit"
|
|
509
|
-
@tier "policy"
|
|
510
|
-
autoApproveBelowThreshold : boolean = true
|
|
511
|
-
@label "Skip review queue for low-value requests?"
|
|
512
|
-
@description "When true, auto-approves requests below the threshold without queuing. v1.0 declarative only."
|
|
513
|
-
@synonyms "auto approve, skip review, bypass queue, automatic approval"
|
|
514
|
-
@tier "policy"
|
|
515
|
-
valueField : string = ""
|
|
516
|
-
@label "Value field"
|
|
517
|
-
@description "Payload field name to compare against threshold (e.g. 'amount' on a RefundRequested event). v1.0 declarative only."
|
|
518
|
-
@tier "internal"
|
|
519
|
-
escalationHours : number = 0
|
|
520
|
-
@label "Escalate after how many hours pending?"
|
|
521
|
-
@description "Hours a request can sit pending before escalating. v1.0 declarative only."
|
|
522
|
-
@synonyms "escalation time, SLA hours, pending timeout, escalate after"
|
|
523
|
-
@tier "policy"
|
|
524
|
-
escalationRoles : [string] = []
|
|
525
|
-
@label "Who gets notified when a request escalates?"
|
|
526
|
-
@description "Roles notified on escalation (compose sibling std-notify-on-event to deliver)."
|
|
527
|
-
@synonyms "escalation contacts, escalate to, notify roles, escalated approver"
|
|
528
|
-
@tier "policy"
|
|
529
490
|
tableLook : "dense" | "spacious" | "striped" | "borderless" | "card-rows" = dense
|
|
530
491
|
@label "Review queue table style"
|
|
531
492
|
@description "Visual treatment for the approval-queue data table."
|
|
@@ -535,6 +496,29 @@ orbital ApprovalGateOrbital {
|
|
|
535
496
|
@label "Review slot"
|
|
536
497
|
@description "UI slot the review queue renders into. Defaults to the modal overlay so the queue never seizes the host's main content; summoned via OPEN, cleared via CLOSE."
|
|
537
498
|
@tier "internal"
|
|
499
|
+
itemActions : [ItemAction] = [{
|
|
500
|
+
event: OPEN_SUBJECT
|
|
501
|
+
icon: eye
|
|
502
|
+
label: View
|
|
503
|
+
variant: ghost
|
|
504
|
+
}, {
|
|
505
|
+
event: APPROVE
|
|
506
|
+
icon: check
|
|
507
|
+
label: Approve
|
|
508
|
+
variant: primary
|
|
509
|
+
}, {
|
|
510
|
+
event: DENY
|
|
511
|
+
icon: x
|
|
512
|
+
label: Deny
|
|
513
|
+
variant: danger
|
|
514
|
+
}]
|
|
515
|
+
@label "Row actions"
|
|
516
|
+
@description "Actions offered on each row; give an item `roles` to show it only to those viewer roles."
|
|
517
|
+
@tier "presentation"
|
|
518
|
+
viewerRole : string = ""
|
|
519
|
+
@label "Viewer's role"
|
|
520
|
+
@description "The signed-in viewer's role that each action's `roles` is checked against. Bind it explicitly at the call site (e.g. `viewerRole: @user.role`) in an app whose identity carries a role; left empty, only actions with no `roles` show."
|
|
521
|
+
@tier "policy"
|
|
538
522
|
}
|
|
539
523
|
}
|
|
540
524
|
|
|
@@ -93,11 +93,6 @@ orbital AuditCaptureOrbital {
|
|
|
93
93
|
@description "Store a full before-and-after snapshot of each change. More detail, but a larger audit log."
|
|
94
94
|
@synonyms "before after, snapshot, diff, change snapshot, field diff"
|
|
95
95
|
@tier "policy"
|
|
96
|
-
retentionDays : number = 2555
|
|
97
|
-
@label "How long should the audit log be kept (days)?"
|
|
98
|
-
@description "Number of days to retain audit entries. Default 2555 ≈ 7 years, typical for compliance."
|
|
99
|
-
@synonyms "log retention, keep for, audit expiry, retention period, log lifetime"
|
|
100
|
-
@tier "policy"
|
|
101
96
|
}
|
|
102
97
|
}
|
|
103
98
|
|
|
@@ -254,10 +254,6 @@ orbital CacheEntryOrbital {
|
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
listens {
|
|
257
|
-
FetchButton.FETCH -> FETCH
|
|
258
|
-
InvalidateButton.INVALIDATE -> INVALIDATE
|
|
259
|
-
RefreshButton.REFRESH -> REFRESH
|
|
260
|
-
RetryButton.FETCH -> FETCH
|
|
261
257
|
CACHED {
|
|
262
258
|
data : CacheEntry
|
|
263
259
|
}
|
|
@@ -281,26 +277,6 @@ orbital CacheEntryOrbital {
|
|
|
281
277
|
}
|
|
282
278
|
|
|
283
279
|
config {
|
|
284
|
-
ttlSeconds : number = 300
|
|
285
|
-
@label "TTL (seconds)"
|
|
286
|
-
@description "Cache entry time-to-live before it goes stale. Default 5 minutes. Shorter = fresher/real-time data; longer = stable/long-lived caching."
|
|
287
|
-
@synonyms "expiration, time to live, cache duration, freshness, real-time (short) vs long-lived (long)"
|
|
288
|
-
@tier "domain"
|
|
289
|
-
staleWhileRevalidate : boolean = true
|
|
290
|
-
@label "Serve stale while revalidating"
|
|
291
|
-
@description "When true, serve stale entries to consumers while a background refresh fetches fresh data. Reduces latency at the cost of brief staleness."
|
|
292
|
-
@synonyms "SWR, stale serving"
|
|
293
|
-
@tier "domain"
|
|
294
|
-
evictionPolicy : "lru" | "lfu" | "fifo" | "ttl-only" = lru
|
|
295
|
-
@label "Eviction policy"
|
|
296
|
-
@description "How entries are evicted when the cache fills: least-recently-used, least-frequently-used, first-in-first-out, or TTL-only (never evict early)."
|
|
297
|
-
@synonyms "cache replacement, eviction strategy"
|
|
298
|
-
@tier "domain"
|
|
299
|
-
maxCacheSize : number = 1000
|
|
300
|
-
@label "Max cache entries"
|
|
301
|
-
@description "Hard cap on cached entries before eviction. 0 = unlimited."
|
|
302
|
-
@synonyms "cache capacity, max entries"
|
|
303
|
-
@tier "domain"
|
|
304
280
|
emptyLook : "illustrated" | "icon-only" | "text-only" | "mascot" = icon-only
|
|
305
281
|
@label "Empty-state look"
|
|
306
282
|
@description "Layer 2 visual treatment for the empty-state placeholder."
|
|
@@ -147,7 +147,7 @@ orbital ServiceNodeOrbital {
|
|
|
147
147
|
INIT -> closed
|
|
148
148
|
(set @entity.failureCount 0)
|
|
149
149
|
(set @entity.successCount 0)
|
|
150
|
-
(set @entity.threshold
|
|
150
|
+
(set @entity.threshold @config.failureThreshold)
|
|
151
151
|
(fetch ServiceNode {
|
|
152
152
|
emit: { failure: ServiceNodeLoadFailed, success: ServiceNodeLoaded }
|
|
153
153
|
})
|
|
@@ -332,7 +332,6 @@ orbital ServiceNodeOrbital {
|
|
|
332
332
|
}
|
|
333
333
|
|
|
334
334
|
listens {
|
|
335
|
-
ResetButton.RESET -> RESET
|
|
336
335
|
ServiceNodeLoadFailed {
|
|
337
336
|
message : string
|
|
338
337
|
}
|
|
@@ -347,21 +346,6 @@ orbital ServiceNodeOrbital {
|
|
|
347
346
|
@description "Number of consecutive failures before the circuit opens and starts rejecting requests."
|
|
348
347
|
@synonyms "open trigger, failure count"
|
|
349
348
|
@tier "domain"
|
|
350
|
-
cooldownSeconds : number = 30
|
|
351
|
-
@label "Cooldown (seconds)"
|
|
352
|
-
@description "Seconds the circuit stays open before transitioning to half-open and probing for recovery."
|
|
353
|
-
@synonyms "reset timeout, open duration"
|
|
354
|
-
@tier "domain"
|
|
355
|
-
halfOpenRequests : number = 1
|
|
356
|
-
@label "Half-open probe requests"
|
|
357
|
-
@description "Probe requests allowed through in the half-open state before deciding to close or re-open. Lower = cautious single-probe recovery; higher = aggressive parallel re-validation."
|
|
358
|
-
@synonyms "probe count, recovery test size, probe aggressiveness, recovery test volume, cautious vs fast recovery"
|
|
359
|
-
@tier "domain"
|
|
360
|
-
fallbackBehavior : "reject" | "cached-response" | "queue" | "static-default" = reject
|
|
361
|
-
@label "Fallback behavior"
|
|
362
|
-
@description "What to return to callers while the circuit is open: reject = fail-fast/strict, cached-response = graceful degrade with stale data, queue = retry-later/no data loss, static-default = safe placeholder."
|
|
363
|
-
@synonyms "open-state response, degraded mode, fail-fast vs graceful degrade"
|
|
364
|
-
@tier "domain"
|
|
365
349
|
statLook : "elevated" | "flat" | "progress-backed" | "gauge" | "sparkline" = elevated
|
|
366
350
|
@label "Stat display look"
|
|
367
351
|
@description "Layer 2 visual treatment for stat / KPI cards."
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
app std-data-erasure "1.0.0"
|
|
2
2
|
"std-data-erasure — GDPR Art. 17 right-to-be-forgotten queue. Tracks ErasureRequest rows through pending → grace → executed lifecycle with Cancel during grace. v1.0 ships the request lifecycle UI + knob set; auto-emit of ExecuteErasure after grace lands in v1.1 (loop-with-emit gap — docs/Almadar_Std_Factories.md). Target app/ atoms then own the actual delete or piiFields scrub via an ExecuteErasure listener."
|
|
3
|
+
type ItemAction = { label : string!, event : event, variant : string, icon : string, roles : [string] }
|
|
3
4
|
orbital DataErasureOrbital {
|
|
4
5
|
uses Spinner from "std/behaviors/ui-spinner"
|
|
5
6
|
uses Typography from "std/behaviors/ui-typography"
|
|
@@ -112,7 +113,7 @@ orbital DataErasureOrbital {
|
|
|
112
113
|
})
|
|
113
114
|
ExecScanLoaded -> execScanning when (and @config.enabled [">", (array/len ?data), 0])
|
|
114
115
|
(set @entity.id (object/get (array/first ?data) id))
|
|
115
|
-
(set @entity.targetEntity (object/get (array/first ?data) targetEntity))
|
|
116
|
+
(set @entity.targetEntity (str/default (object/get (array/first ?data) targetEntity) @config.targetEntity))
|
|
116
117
|
(set @entity.subjectId (object/get (array/first ?data) subjectId))
|
|
117
118
|
(emit ExecuteErasure {
|
|
118
119
|
requestId: @entity.id
|
|
@@ -139,7 +140,7 @@ orbital DataErasureOrbital {
|
|
|
139
140
|
})
|
|
140
141
|
ExecScanLoaded -> execScanning when [">", (array/len ?data), 0]
|
|
141
142
|
(set @entity.id (object/get (array/first ?data) id))
|
|
142
|
-
(set @entity.targetEntity (object/get (array/first ?data) targetEntity))
|
|
143
|
+
(set @entity.targetEntity (str/default (object/get (array/first ?data) targetEntity) @config.targetEntity))
|
|
143
144
|
(set @entity.subjectId (object/get (array/first ?data) subjectId))
|
|
144
145
|
(emit ExecuteErasure {
|
|
145
146
|
requestId: @entity.id
|
|
@@ -191,12 +192,7 @@ orbital DataErasureOrbital {
|
|
|
191
192
|
variant: caption
|
|
192
193
|
}]
|
|
193
194
|
gap: sm
|
|
194
|
-
itemActions: [
|
|
195
|
-
event: CANCEL_ERASURE
|
|
196
|
-
icon: x
|
|
197
|
-
label: Cancel
|
|
198
|
-
variant: secondary
|
|
199
|
-
}]
|
|
195
|
+
itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
|
|
200
196
|
look: @config.tableLook
|
|
201
197
|
type: data-grid
|
|
202
198
|
}]
|
|
@@ -316,7 +312,6 @@ orbital DataErasureOrbital {
|
|
|
316
312
|
}
|
|
317
313
|
|
|
318
314
|
listens {
|
|
319
|
-
CloseButton.CLOSE -> CLOSE
|
|
320
315
|
ExecScanLoaded {
|
|
321
316
|
data : [ErasureRequest]
|
|
322
317
|
}
|
|
@@ -396,21 +391,6 @@ orbital DataErasureOrbital {
|
|
|
396
391
|
@label "Target entity"
|
|
397
392
|
@description "Entity name whose records erasure requests apply to (e.g. 'CustomerAccount')."
|
|
398
393
|
@tier "internal"
|
|
399
|
-
gracePeriodDays : number = 30
|
|
400
|
-
@label "How many days before deletion is carried out?"
|
|
401
|
-
@description "Days between request submission and execution. The subject can cancel during this window."
|
|
402
|
-
@synonyms "grace period, cancellation window, deletion delay, days before delete"
|
|
403
|
-
@tier "policy"
|
|
404
|
-
anonymizeVsDelete : "anonymize" | "delete" = anonymize
|
|
405
|
-
@label "Anonymize or fully delete the record?"
|
|
406
|
-
@description "anonymize = scrub PII fields and keep row for audit; delete = remove the row entirely."
|
|
407
|
-
@synonyms "deletion mode, anonymize, delete, scrub or remove, retention mode"
|
|
408
|
-
@tier "policy"
|
|
409
|
-
piiFields : [string] = []
|
|
410
|
-
@label "Which fields contain personal data to scrub?"
|
|
411
|
-
@description "Fields the target atom nulls when anonymizing (e.g. email, name, phone)."
|
|
412
|
-
@synonyms "PII fields, personal data fields, sensitive fields, fields to scrub"
|
|
413
|
-
@tier "policy"
|
|
414
394
|
tableLook : "dense" | "spacious" | "striped" | "borderless" | "card-rows" = dense
|
|
415
395
|
@label "Erasure queue table style"
|
|
416
396
|
@description "Visual treatment for the erasure-requests data table."
|
|
@@ -420,6 +400,19 @@ orbital DataErasureOrbital {
|
|
|
420
400
|
@label "Review slot"
|
|
421
401
|
@description "UI slot the erasure-requests queue renders into. Defaults to the modal overlay so it never seizes the host's main content; summoned via OPEN, cleared via CLOSE."
|
|
422
402
|
@tier "internal"
|
|
403
|
+
itemActions : [ItemAction] = [{
|
|
404
|
+
event: CANCEL_ERASURE
|
|
405
|
+
icon: x
|
|
406
|
+
label: Cancel
|
|
407
|
+
variant: secondary
|
|
408
|
+
}]
|
|
409
|
+
@label "Row actions"
|
|
410
|
+
@description "Actions offered on each row; give an item `roles` to show it only to those viewer roles."
|
|
411
|
+
@tier "presentation"
|
|
412
|
+
viewerRole : string = ""
|
|
413
|
+
@label "Viewer's role"
|
|
414
|
+
@description "The signed-in viewer's role that each action's `roles` is checked against. Bind it explicitly at the call site (e.g. `viewerRole: @user.role`) in an app whose identity carries a role; left empty, only actions with no `roles` show."
|
|
415
|
+
@tier "policy"
|
|
423
416
|
}
|
|
424
417
|
}
|
|
425
418
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
app std-data-import "1.0.0"
|
|
2
|
-
"std-data-import — staged CSV import run, source-agnostic: upload → staged review → confirm → parse+map → handoff. UPLOAD_CSV opens a run and persists an ImportBatch row (status uploaded, fieldMappingJson recorded verbatim for provenance); the host's file UI parses the CSV and answers with STAGE_ROWS, one JSON string per raw row, which the atom bulk-persists into import_rows against the batch id and presents as a staged review (row/error counts + Confirm/Discard). CONFIRM_IMPORT marks the batch confirmed, emits IMPORT_CONFIRMED { batchId, sourceName, rowCount }, and fetches the batch's staged rows; on fetch success the atom parses each rowJson via json/parse, remaps keys through the batch's mappingJson, and emits IMPORT_ROWS_PARSED { batchId, rows, failed } — the persist half is the CONSUMER organism's: it listens for IMPORT_ROWS_PARSED and persists the mapped rows into its own target entity (cross-atom persist into a consumer's entity is not expressible from here). This is deliberately the CSV-file path: the atom never calls a source service — sourceName/fieldMappingJson/targetEntity
|
|
2
|
+
"std-data-import — staged CSV import run, source-agnostic: upload → staged review → confirm → parse+map → handoff. UPLOAD_CSV opens a run and persists an ImportBatch row (status uploaded, fieldMappingJson recorded verbatim for provenance); the host's file UI parses the CSV and answers with STAGE_ROWS, one JSON string per raw row, which the atom bulk-persists into import_rows against the batch id and presents as a staged review (row/error counts + Confirm/Discard). CONFIRM_IMPORT marks the batch confirmed, emits IMPORT_CONFIRMED { batchId, sourceName, rowCount }, and fetches the batch's staged rows; on fetch success the atom parses each rowJson via json/parse, remaps keys through the batch's mappingJson, and emits IMPORT_ROWS_PARSED { batchId, rows, failed } — the persist half is the CONSUMER organism's: it listens for IMPORT_ROWS_PARSED and persists the mapped rows into its own target entity (cross-atom persist into a consumer's entity is not expressible from here). This is deliberately the CSV-file path: the atom never calls a source service — sourceName/fieldMappingJson/targetEntity are consumer configs, and any persist failure marks the batch row failed and fires IMPORT_FAILED, never a silent swallow. Compose with std-import for the file-picker menu."
|
|
3
3
|
orbital DataImportOrbital {
|
|
4
4
|
type DataImportFile = { name : string!, size : number, type : string, content : string }
|
|
5
5
|
|
|
@@ -218,6 +218,7 @@ orbital DataImportOrbital {
|
|
|
218
218
|
(fn k (if (object/has (json/parse @entity.mappingJson) @k)
|
|
219
219
|
(object/get (json/parse @entity.mappingJson) @k)
|
|
220
220
|
@k)))))
|
|
221
|
+
targetEntity: @config.targetEntity
|
|
221
222
|
})
|
|
222
223
|
;; Same transient-failure self-loop as in `staged` — the row fetch can
|
|
223
224
|
;; fail after the batch row was already persisted as confirmed.
|
|
@@ -284,6 +285,7 @@ orbital DataImportOrbital {
|
|
|
284
285
|
batchId : string!
|
|
285
286
|
failed : number
|
|
286
287
|
rows : [Map string scalar]
|
|
288
|
+
targetEntity : string
|
|
287
289
|
}
|
|
288
290
|
@description "Confirmed rows parsed and key-mapped: each staged row's rowJson was parsed via json/parse and remapped through the batch's mappingJson; failed counts rows whose rowJson did not parse to an object (surfaced, never dropped). The consumer persists rows into its own target entity and marks them imported."
|
|
289
291
|
@synonyms "rows parsed, rows mapped, import rows ready"
|
|
@@ -330,21 +332,16 @@ orbital DataImportOrbital {
|
|
|
330
332
|
@description "Free-form name of the upstream source this import pulls from — whatever tool or file export the user names. Recorded on the batch row for provenance and echoed on IMPORT_CONFIRMED."
|
|
331
333
|
@synonyms "source, origin, import from, provider name, data source"
|
|
332
334
|
@tier "domain"
|
|
335
|
+
targetEntity : string = ""
|
|
336
|
+
@label "Target entity"
|
|
337
|
+
@description "Name of the consumer organism's entity the staged rows land in after confirm. Carried on IMPORT_ROWS_PARSED so the consumer's persist half knows where the mapped rows belong — the atom never writes the target entity itself."
|
|
338
|
+
@synonyms "destination, import into, target type"
|
|
339
|
+
@tier "domain"
|
|
333
340
|
fieldMappingJson : string = "{}"
|
|
334
341
|
@label "Field mapping (JSON)"
|
|
335
342
|
@description "JSON object mapping source CSV column names to target field names. Stored verbatim on the batch row (mappingJson); the atom applies it when it parses staged rows into IMPORT_ROWS_PARSED, so the consumer persists already-mapped rows into the target entity."
|
|
336
343
|
@synonyms "field mapping, column mapping, map columns, remap fields, csv columns"
|
|
337
344
|
@tier "domain"
|
|
338
|
-
targetEntity : string = ""
|
|
339
|
-
@label "Target entity"
|
|
340
|
-
@description "Name of the consumer organism's entity the staged rows land in after confirm. Declarative contract only — the atom never writes the target entity; the consumer persists on IMPORT_CONFIRMED."
|
|
341
|
-
@synonyms "destination, import into, target type"
|
|
342
|
-
@tier "domain"
|
|
343
|
-
historyWindowDays : number = 0
|
|
344
|
-
@label "Historical data range (days)"
|
|
345
|
-
@description "How many days back an import may reach (0 = unbounded). A declared import-config knob for the consumer's staging/mapping layer — the atom stages whatever rows it is handed and never filters by date."
|
|
346
|
-
@synonyms "history window, historical range, import range, days back, lookback period"
|
|
347
|
-
@tier "policy"
|
|
348
345
|
}
|
|
349
346
|
}
|
|
350
347
|
|
|
@@ -269,11 +269,6 @@ orbital KnowledgeLoopOrbital {
|
|
|
269
269
|
}
|
|
270
270
|
|
|
271
271
|
listens {
|
|
272
|
-
SurvivedButton.SURVIVED -> SURVIVED
|
|
273
|
-
FailedButton.FAILED -> FAILED
|
|
274
|
-
ChecksAgreeButton.CHECKS_AGREE -> CHECKS_AGREE
|
|
275
|
-
ChecksDisagreeButton.CHECKS_DISAGREE -> CHECKS_DISAGREE
|
|
276
|
-
ChooseNextTargetButton.CHOOSE_NEXT_TARGET -> CHOOSE_NEXT_TARGET
|
|
277
272
|
CONFIRM_SCORE {
|
|
278
273
|
data: ScoreCommit
|
|
279
274
|
}
|
|
@@ -25,7 +25,9 @@ orbital LifecycleOrbital {
|
|
|
25
25
|
|
|
26
26
|
state idle {
|
|
27
27
|
INIT -> idle
|
|
28
|
-
ScanRecordsLoaded ->
|
|
28
|
+
ScanRecordsLoaded -> idle when (and @config.enabled @config.dryRun [">", (array/len ?data), 0])
|
|
29
|
+
(notify info (str/concat "Dry run — " (array/len ?data) " record(s) would transition, nothing was written."))
|
|
30
|
+
ScanRecordsLoaded -> scanning when (and @config.enabled (not @config.dryRun) [">", (array/len ?data), 0])
|
|
29
31
|
(set @entity.headId (object/get (array/first ?data) id))
|
|
30
32
|
(set @entity.headStatus @config.toStatus)
|
|
31
33
|
(emit LifecycleTransitioned { entityId: @entity.headId, status: @entity.headStatus })
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
app std-mod-queue "1.0.0"
|
|
2
2
|
"std-mod-queue — moderation queue for content review. Owns a ModQueueItem entity (one row per flagged target) and a single review trait that loads pending items, renders them in a data-grid with Approve / Reject / Escalate actions, and persists the reviewer's verdict back to the row."
|
|
3
|
+
type ItemAction = { label : string!, event : event, variant : string, icon : string, roles : [string], when : SExpr }
|
|
3
4
|
orbital ModQueueItemOrbital {
|
|
4
5
|
uses Spinner from "std/behaviors/ui-spinner"
|
|
5
6
|
uses Typography from "std/behaviors/ui-typography"
|
|
@@ -106,7 +107,21 @@ orbital ModQueueItemOrbital {
|
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
state loading {
|
|
109
|
-
ModQueueItemLoaded ->
|
|
110
|
+
ModQueueItemLoaded -> loading when [">", (array/len (array/filter ?data (fn row (and ["=", (object/get @row "status"), pending] [">=", (object/get @row "flagCount"), @config.autoEscalateThreshold])))), 0]
|
|
111
|
+
(set @entity.id (object/get (array/first (array/filter ?data (fn row (and ["=", (object/get @row "status"), pending] [">=", (object/get @row "flagCount"), @config.autoEscalateThreshold])))) id))
|
|
112
|
+
(persist update ModQueueItem { id: @entity.id, status: escalated } {
|
|
113
|
+
emit: { failure: ModQueueItemReviewFailed, success: ModQueueItemReviewed }
|
|
114
|
+
})
|
|
115
|
+
ModQueueItemReviewed -> loading
|
|
116
|
+
(fetch ModQueueItem {
|
|
117
|
+
emit: { failure: ModQueueItemLoadFailed, success: ModQueueItemLoaded }
|
|
118
|
+
})
|
|
119
|
+
ModQueueItemReviewFailed -> error
|
|
120
|
+
(render-ui @config.reviewSlot {
|
|
121
|
+
children: [@trait.ErrorAlert]
|
|
122
|
+
type: stack
|
|
123
|
+
})
|
|
124
|
+
ModQueueItemLoaded -> reviewing when ["=", (array/len (array/filter ?data (fn row (and ["=", (object/get @row "status"), pending] [">=", (object/get @row "flagCount"), @config.autoEscalateThreshold])))), 0]
|
|
110
125
|
(render-ui @config.reviewSlot {
|
|
111
126
|
children: [{
|
|
112
127
|
align: center
|
|
@@ -142,22 +157,7 @@ orbital ModQueueItemOrbital {
|
|
|
142
157
|
variant: badge
|
|
143
158
|
}]
|
|
144
159
|
gap: sm
|
|
145
|
-
itemActions: [
|
|
146
|
-
event: APPROVE
|
|
147
|
-
icon: check
|
|
148
|
-
label: Approve
|
|
149
|
-
variant: primary
|
|
150
|
-
}, {
|
|
151
|
-
event: REJECT
|
|
152
|
-
icon: x
|
|
153
|
-
label: Reject
|
|
154
|
-
variant: danger
|
|
155
|
-
}, {
|
|
156
|
-
event: ESCALATE
|
|
157
|
-
icon: alert-triangle
|
|
158
|
-
label: Escalate
|
|
159
|
-
variant: secondary
|
|
160
|
-
}]
|
|
160
|
+
itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
|
|
161
161
|
look: @config.tableLook
|
|
162
162
|
type: data-grid
|
|
163
163
|
}]
|
|
@@ -275,7 +275,6 @@ orbital ModQueueItemOrbital {
|
|
|
275
275
|
}
|
|
276
276
|
|
|
277
277
|
listens {
|
|
278
|
-
CloseButton.CLOSE -> CLOSE
|
|
279
278
|
OPEN
|
|
280
279
|
@description "Summons the moderation queue (host nav/affordance requests it)."
|
|
281
280
|
@synonyms "open, show, review, view queue, moderation queue"
|
|
@@ -353,6 +352,29 @@ orbital ModQueueItemOrbital {
|
|
|
353
352
|
@label "Review slot"
|
|
354
353
|
@description "UI slot the moderation queue renders into. Defaults to the modal overlay so it never seizes the host's main content; summoned via OPEN, cleared via CLOSE."
|
|
355
354
|
@tier "internal"
|
|
355
|
+
itemActions : [ItemAction] = [{
|
|
356
|
+
event: APPROVE
|
|
357
|
+
icon: check
|
|
358
|
+
label: Approve
|
|
359
|
+
variant: primary
|
|
360
|
+
}, {
|
|
361
|
+
event: REJECT
|
|
362
|
+
icon: x
|
|
363
|
+
label: Reject
|
|
364
|
+
variant: danger
|
|
365
|
+
}, {
|
|
366
|
+
event: ESCALATE
|
|
367
|
+
icon: alert-triangle
|
|
368
|
+
label: Escalate
|
|
369
|
+
variant: secondary
|
|
370
|
+
}]
|
|
371
|
+
@label "Row actions"
|
|
372
|
+
@description "Actions offered on each row; give an item `roles` to show it only to those viewer roles."
|
|
373
|
+
@tier "presentation"
|
|
374
|
+
viewerRole : string = ""
|
|
375
|
+
@label "Viewer's role"
|
|
376
|
+
@description "The signed-in viewer's role that each action's `roles` is checked against. Bind it explicitly at the call site (e.g. `viewerRole: @user.role`) in an app whose identity carries a role; left empty, only actions with no `roles` show."
|
|
377
|
+
@tier "policy"
|
|
356
378
|
}
|
|
357
379
|
}
|
|
358
380
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
app std-notification-preferences "1.0.0"
|
|
2
2
|
"std-notification-preferences — per-person notification preference store plus a consultable gate. Owns NotificationPreference rows (one per person + event key: channel override in_app/email/push/slack/sms/webhook, mode instant/digest/off, quiet-hours window 'HH:MM-HH:MM' such as 22:00-07:00). The PreferencesManage trait is standard CRUD over the store (list / create / update / delete, persisted, success/failure cascade arms): a data-grid browse plus ModalRecordModal create/edit forms whose SAVE carries the full row payload (std-list daisy-chain idiom). The PreferenceGate trait is the consult half other notify traits call: emit CHECK_PREFERENCE { personId, eventKey } and the gate fetches the matching row (a row whose eventKey is blank applies to every event) and answers PREFERENCE_RESOLVED { personId, eventKey, channel, mode, suppressed } — suppressed is true only when the row's quietHours window covers the current hour; mode 'digest' rides on the verdict for the caller to defer. Default policy: no matching row — or a failed lookup — resolves fail-open to { channel: in_app, mode: instant, suppressed: false }; the absence of a preference never silences a notification."
|
|
3
|
+
type ItemAction = { label : string!, event : event, variant : string, icon : string, roles : [string], when : SExpr }
|
|
3
4
|
orbital NotificationPreferencesOrbital {
|
|
4
5
|
uses Modal from "std/behaviors/std-modal"
|
|
5
6
|
|
|
@@ -102,17 +103,7 @@ orbital NotificationPreferencesOrbital {
|
|
|
102
103
|
variant: caption
|
|
103
104
|
}]
|
|
104
105
|
gap: sm
|
|
105
|
-
itemActions: [
|
|
106
|
-
event: EDIT
|
|
107
|
-
icon: pencil
|
|
108
|
-
label: Edit
|
|
109
|
-
variant: secondary
|
|
110
|
-
}, {
|
|
111
|
-
event: DELETE
|
|
112
|
-
icon: trash-2
|
|
113
|
-
label: Delete
|
|
114
|
-
variant: danger
|
|
115
|
-
}]
|
|
106
|
+
itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
|
|
116
107
|
look: @config.tableLook
|
|
117
108
|
type: data-grid
|
|
118
109
|
}]
|
|
@@ -342,6 +333,24 @@ orbital NotificationPreferencesOrbital {
|
|
|
342
333
|
@label "Table look"
|
|
343
334
|
@description "Layer 2 visual treatment for the preference data table rendered by this atom."
|
|
344
335
|
@tier "presentation"
|
|
336
|
+
itemActions : [ItemAction] = [{
|
|
337
|
+
event: EDIT
|
|
338
|
+
icon: pencil
|
|
339
|
+
label: Edit
|
|
340
|
+
variant: secondary
|
|
341
|
+
}, {
|
|
342
|
+
event: DELETE
|
|
343
|
+
icon: trash-2
|
|
344
|
+
label: Delete
|
|
345
|
+
variant: danger
|
|
346
|
+
}]
|
|
347
|
+
@label "Row actions"
|
|
348
|
+
@description "Actions offered on each row; give an item `roles` to show it only to those viewer roles."
|
|
349
|
+
@tier "presentation"
|
|
350
|
+
viewerRole : string = ""
|
|
351
|
+
@label "Viewer's role"
|
|
352
|
+
@description "The signed-in viewer's role that each action's `roles` is checked against. Bind it explicitly at the call site (e.g. `viewerRole: @user.role`) in an app whose identity carries a role; left empty, only actions with no `roles` show."
|
|
353
|
+
@tier "policy"
|
|
345
354
|
}
|
|
346
355
|
}
|
|
347
356
|
|
|
@@ -382,11 +382,6 @@ orbital NotifyOnEventOrbital {
|
|
|
382
382
|
@description "Threshold compared against `guardField` when `guardOp` is not `eq` (e.g. fire when stock drops below 5)."
|
|
383
383
|
@synonyms "threshold, cutoff, limit, watermark, trigger value"
|
|
384
384
|
@tier "policy"
|
|
385
|
-
listensFor : [string] = []
|
|
386
|
-
@label "Trigger events"
|
|
387
|
-
@description "Event names that should fire a notification. Set this to the upstream event name (e.g. OrderPlaced, CheckoutCompleted) so this atom listens for events from the orbital that emits them. The orbital owning this trait reacts whenever the named event fires anywhere in the schema."
|
|
388
|
-
@synonyms "subscribe to event, listen for event, react to event, watch for, wire upstream event, observe event from another orbital, cross-orbital subscription, on-event trigger"
|
|
389
|
-
@tier "internal"
|
|
390
385
|
eventKey : string = ""
|
|
391
386
|
@label "Event key for preferences"
|
|
392
387
|
@description "Stable key naming the upstream event this listener is bound to (e.g. 'OrderPlaced'). NotificationPreference rows (std-notification-center) whose eventKey equals this key — or is blank — apply to this listener's dispatches."
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
app std-permission-matrix "1.0.0"
|
|
2
2
|
"std-permission-matrix — role × module permission grant table / capability matrix admin surface. Use when a user voices that permissions must be managed per role and module (permission matrix, role permissions, capability matrix, permission grants, access matrix, who can see finance, hide margins, module-level permissions, admin permission screen, grant management, finance visibility by role, restrict modules by role). Persists PermissionGrant rows (workspaceId + role + module + capability flags canReadFinance / canSeeOthersHours / canSeeMargins) with full CRUD on an admin page mounted at /admin/permissions — create/edit forms are the std-modal ModalRecordModal substrate (the corpus's two-trait CRUD shape, mirroring std-list), persists live in a sibling coordinator trait, and adminRoles is ENFORCED at the persist boundary (a viewer whose role is not listed cannot fire a write, from the button or from the bus). Ships a query trait other traits consult event-wise: CHECK_GRANT { role, module } fetches the matching grant(s) and re-emits GRANT_RESOLVED { role, module, canReadFinance, canSeeOthersHours, canSeeMargins, found }. Grant SURFACE only — entity-layer @read/@update gate integration is a recorded core gap (gates are pure @entity/@user S-expressions and cannot consult another entity's rows), so enforcement stays with the consumer until that core lands."
|
|
3
|
+
type ItemAction = { label : string!, event : event, variant : string, icon : string, roles : [string], when : SExpr }
|
|
3
4
|
orbital PermissionMatrixOrbital {
|
|
4
5
|
uses Modal from "std/behaviors/std-modal"
|
|
5
6
|
uses Spinner from "std/behaviors/ui-spinner"
|
|
@@ -161,17 +162,7 @@ orbital PermissionMatrixOrbital {
|
|
|
161
162
|
variant: caption
|
|
162
163
|
}]
|
|
163
164
|
gap: sm
|
|
164
|
-
itemActions: [
|
|
165
|
-
event: EDIT
|
|
166
|
-
icon: pencil
|
|
167
|
-
label: Edit
|
|
168
|
-
variant: ghost
|
|
169
|
-
}, {
|
|
170
|
-
event: DELETE
|
|
171
|
-
icon: trash
|
|
172
|
-
label: Delete
|
|
173
|
-
variant: danger
|
|
174
|
-
}]
|
|
165
|
+
itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
|
|
175
166
|
type: data-grid
|
|
176
167
|
}]
|
|
177
168
|
direction: vertical
|
|
@@ -255,6 +246,27 @@ orbital PermissionMatrixOrbital {
|
|
|
255
246
|
}
|
|
256
247
|
|
|
257
248
|
config {}
|
|
249
|
+
|
|
250
|
+
config {
|
|
251
|
+
itemActions : [ItemAction] = [{
|
|
252
|
+
event: EDIT
|
|
253
|
+
icon: pencil
|
|
254
|
+
label: Edit
|
|
255
|
+
variant: ghost
|
|
256
|
+
}, {
|
|
257
|
+
event: DELETE
|
|
258
|
+
icon: trash
|
|
259
|
+
label: Delete
|
|
260
|
+
variant: danger
|
|
261
|
+
}]
|
|
262
|
+
@label "Row actions"
|
|
263
|
+
@description "Actions offered on each row; give an item `roles` to show it only to those viewer roles."
|
|
264
|
+
@tier "presentation"
|
|
265
|
+
viewerRole : string = ""
|
|
266
|
+
@label "Viewer's role"
|
|
267
|
+
@description "The signed-in viewer's role that each action's `roles` is checked against. Bind it explicitly at the call site (e.g. `viewerRole: @user.role`) in an app whose identity carries a role; left empty, only actions with no `roles` show."
|
|
268
|
+
@tier "policy"
|
|
269
|
+
}
|
|
258
270
|
}
|
|
259
271
|
|
|
260
272
|
;; Create modal: configured via `config`, no effects overrides (std-list
|