openxiangda 2.0.0-alpha.26 → 2.0.0-alpha.27
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/dist/nest.d.ts +2 -2
- package/dist/nest.d.ts.map +1 -1
- package/dist/nest.js +1 -1
- package/dist/nest.js.map +1 -1
- package/package.json +7 -7
- package/skills/manifest.json +1 -1
- package/skills/openxiangda-v2/SKILL.md +3 -3
- package/skills/openxiangda-v2/references/backend.md +85 -2
- package/skills/openxiangda-v2/references/workflow-events.md +17 -0
- package/skills/openxiangda-v2/references/workspace.md +1 -1
package/dist/nest.d.ts
CHANGED
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
* Applications receive only current-user-union, Perspective read projection,
|
|
5
5
|
* application-principal, Data API, runtime, event and bounded operation APIs.
|
|
6
6
|
*/
|
|
7
|
-
export { bootstrapOpenXiangdaApplication, OpenXiangdaModule, OpenXiangdaAuthzGuard, RequireCapability, OpenXiangdaOperation, CurrentPrincipal, CurrentUser, CurrentPerspective, currentUserFromVerifiedContext, currentUserFromPrincipal, CurrentApplicationPrincipal, OpenXiangdaDataApiService, OpenXiangdaBusinessDataApiService, OpenXiangdaApplicationDataApiService, OpenXiangdaApplicationCredentials, OpenXiangdaRuntimeLeaseService, OpenXiangdaRuntimeSecrets, OpenXiangdaStandardOperations, OpenXiangdaEventContext, OpenXiangdaEventHandler, OpenXiangdaEventRegistry, OpenXiangdaEventRetryableError, OpenXiangdaEventDeterministicError, eventSigningSecretsFromEnvironment, assertValidTimeInterval, idempotentTransaction, } from 'openxiangda-nest';
|
|
8
|
-
export type { OpenXiangdaApplicationBootstrapOptions, OpenXiangdaModuleOptions, OpenXiangdaOAuthClientOptions, OpenXiangdaFetch, OpenXiangdaCurrentUser, OpenXiangdaServicePrincipal, OpenXiangdaConnectedDevelopmentStatus, OpenXiangdaDomainEventEmitInput, OpenXiangdaDomainEventEmitResult, OpenXiangdaBusinessActionContext, OpenXiangdaRuntimeLeaseState, OpenXiangdaEventHandlerContext, OpenXiangdaEventHandlerDeclaration, OpenXiangdaEventConsumer, TimeInterval, MeetingReservationOperationInput, CourseSelectionOperationInput, VisitorReservationOperationInput, } from 'openxiangda-nest';
|
|
7
|
+
export { bootstrapOpenXiangdaApplication, OpenXiangdaModule, OpenXiangdaAuthzGuard, RequireCapability, OpenXiangdaOperation, CurrentPrincipal, CurrentUser, CurrentPerspective, currentUserFromVerifiedContext, currentUserFromPrincipal, CurrentApplicationPrincipal, OpenXiangdaDataApiService, OpenXiangdaBusinessDataApiService, OpenXiangdaBusinessNotificationService, OpenXiangdaNotificationService, OpenXiangdaApplicationDataApiService, OpenXiangdaApplicationCredentials, OpenXiangdaRuntimeLeaseService, OpenXiangdaRuntimeSecrets, OpenXiangdaStandardOperations, OpenXiangdaEventContext, OpenXiangdaEventHandler, OpenXiangdaEventRegistry, OpenXiangdaEventRetryableError, OpenXiangdaEventDeterministicError, eventSigningSecretsFromEnvironment, assertValidTimeInterval, idempotentTransaction, } from 'openxiangda-nest';
|
|
8
|
+
export type { OpenXiangdaApplicationBootstrapOptions, OpenXiangdaModuleOptions, OpenXiangdaOAuthClientOptions, OpenXiangdaFetch, OpenXiangdaCurrentUser, OpenXiangdaServicePrincipal, OpenXiangdaConnectedDevelopmentStatus, OpenXiangdaDomainEventEmitInput, OpenXiangdaDomainEventEmitResult, OpenXiangdaBusinessActionContext, OpenXiangdaBusinessNotificationInput, OpenXiangdaEventBusinessNotificationInput, OpenXiangdaRuntimeLeaseState, OpenXiangdaEventHandlerContext, OpenXiangdaEventHandlerDeclaration, OpenXiangdaEventConsumer, TimeInterval, MeetingReservationOperationInput, CourseSelectionOperationInput, VisitorReservationOperationInput, } from 'openxiangda-nest';
|
|
9
9
|
//# sourceMappingURL=nest.d.ts.map
|
package/dist/nest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nest.d.ts","sourceRoot":"","sources":["../src/nest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,+BAA+B,EAC/B,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,8BAA8B,EAC9B,wBAAwB,EACxB,2BAA2B,EAC3B,yBAAyB,EACzB,iCAAiC,EACjC,oCAAoC,EACpC,iCAAiC,EACjC,8BAA8B,EAC9B,yBAAyB,EACzB,6BAA6B,EAC7B,uBAAuB,EACvB,uBAAuB,EACvB,wBAAwB,EACxB,8BAA8B,EAC9B,kCAAkC,EAClC,kCAAkC,EAClC,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EACV,sCAAsC,EACtC,wBAAwB,EACxB,6BAA6B,EAC7B,gBAAgB,EAChB,sBAAsB,EACtB,2BAA2B,EAC3B,qCAAqC,EACrC,+BAA+B,EAC/B,gCAAgC,EAChC,gCAAgC,EAChC,4BAA4B,EAC5B,8BAA8B,EAC9B,kCAAkC,EAClC,wBAAwB,EACxB,YAAY,EACZ,gCAAgC,EAChC,6BAA6B,EAC7B,gCAAgC,GACjC,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"nest.d.ts","sourceRoot":"","sources":["../src/nest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,+BAA+B,EAC/B,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,8BAA8B,EAC9B,wBAAwB,EACxB,2BAA2B,EAC3B,yBAAyB,EACzB,iCAAiC,EACjC,sCAAsC,EACtC,8BAA8B,EAC9B,oCAAoC,EACpC,iCAAiC,EACjC,8BAA8B,EAC9B,yBAAyB,EACzB,6BAA6B,EAC7B,uBAAuB,EACvB,uBAAuB,EACvB,wBAAwB,EACxB,8BAA8B,EAC9B,kCAAkC,EAClC,kCAAkC,EAClC,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EACV,sCAAsC,EACtC,wBAAwB,EACxB,6BAA6B,EAC7B,gBAAgB,EAChB,sBAAsB,EACtB,2BAA2B,EAC3B,qCAAqC,EACrC,+BAA+B,EAC/B,gCAAgC,EAChC,gCAAgC,EAChC,oCAAoC,EACpC,yCAAyC,EACzC,4BAA4B,EAC5B,8BAA8B,EAC9B,kCAAkC,EAClC,wBAAwB,EACxB,YAAY,EACZ,gCAAgC,EAChC,6BAA6B,EAC7B,gCAAgC,GACjC,MAAM,kBAAkB,CAAC"}
|
package/dist/nest.js
CHANGED
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
* Applications receive only current-user-union, Perspective read projection,
|
|
5
5
|
* application-principal, Data API, runtime, event and bounded operation APIs.
|
|
6
6
|
*/
|
|
7
|
-
export { bootstrapOpenXiangdaApplication, OpenXiangdaModule, OpenXiangdaAuthzGuard, RequireCapability, OpenXiangdaOperation, CurrentPrincipal, CurrentUser, CurrentPerspective, currentUserFromVerifiedContext, currentUserFromPrincipal, CurrentApplicationPrincipal, OpenXiangdaDataApiService, OpenXiangdaBusinessDataApiService, OpenXiangdaApplicationDataApiService, OpenXiangdaApplicationCredentials, OpenXiangdaRuntimeLeaseService, OpenXiangdaRuntimeSecrets, OpenXiangdaStandardOperations, OpenXiangdaEventContext, OpenXiangdaEventHandler, OpenXiangdaEventRegistry, OpenXiangdaEventRetryableError, OpenXiangdaEventDeterministicError, eventSigningSecretsFromEnvironment, assertValidTimeInterval, idempotentTransaction, } from 'openxiangda-nest';
|
|
7
|
+
export { bootstrapOpenXiangdaApplication, OpenXiangdaModule, OpenXiangdaAuthzGuard, RequireCapability, OpenXiangdaOperation, CurrentPrincipal, CurrentUser, CurrentPerspective, currentUserFromVerifiedContext, currentUserFromPrincipal, CurrentApplicationPrincipal, OpenXiangdaDataApiService, OpenXiangdaBusinessDataApiService, OpenXiangdaBusinessNotificationService, OpenXiangdaNotificationService, OpenXiangdaApplicationDataApiService, OpenXiangdaApplicationCredentials, OpenXiangdaRuntimeLeaseService, OpenXiangdaRuntimeSecrets, OpenXiangdaStandardOperations, OpenXiangdaEventContext, OpenXiangdaEventHandler, OpenXiangdaEventRegistry, OpenXiangdaEventRetryableError, OpenXiangdaEventDeterministicError, eventSigningSecretsFromEnvironment, assertValidTimeInterval, idempotentTransaction, } from 'openxiangda-nest';
|
|
8
8
|
//# sourceMappingURL=nest.js.map
|
package/dist/nest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nest.js","sourceRoot":"","sources":["../src/nest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,+BAA+B,EAC/B,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,8BAA8B,EAC9B,wBAAwB,EACxB,2BAA2B,EAC3B,yBAAyB,EACzB,iCAAiC,EACjC,oCAAoC,EACpC,iCAAiC,EACjC,8BAA8B,EAC9B,yBAAyB,EACzB,6BAA6B,EAC7B,uBAAuB,EACvB,uBAAuB,EACvB,wBAAwB,EACxB,8BAA8B,EAC9B,kCAAkC,EAClC,kCAAkC,EAClC,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"nest.js","sourceRoot":"","sources":["../src/nest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,+BAA+B,EAC/B,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,8BAA8B,EAC9B,wBAAwB,EACxB,2BAA2B,EAC3B,yBAAyB,EACzB,iCAAiC,EACjC,sCAAsC,EACtC,8BAA8B,EAC9B,oCAAoC,EACpC,iCAAiC,EACjC,8BAA8B,EAC9B,yBAAyB,EACzB,6BAA6B,EAC7B,uBAAuB,EACvB,uBAAuB,EACvB,wBAAwB,EACxB,8BAA8B,EAC9B,kCAAkC,EAClC,kCAAkC,EAClC,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openxiangda",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.27",
|
|
4
4
|
"description": "Unified OpenXiangda 2.0 CLI, SDK, React runtime, NestJS integration and AI skill distribution.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -49,12 +49,12 @@
|
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"dayjs": "1.11.18",
|
|
51
51
|
"docx-preview": "0.3.7",
|
|
52
|
-
"openxiangda-cli": "2.0.0-alpha.
|
|
53
|
-
"openxiangda-contracts": "2.0.0-alpha.
|
|
54
|
-
"openxiangda-devkit-core": "2.0.0-alpha.
|
|
55
|
-
"openxiangda-mcp": "2.0.0-alpha.
|
|
56
|
-
"openxiangda-nest": "2.0.0-alpha.
|
|
57
|
-
"openxiangda-skill-kit": "2.0.0-alpha.
|
|
52
|
+
"openxiangda-cli": "2.0.0-alpha.114",
|
|
53
|
+
"openxiangda-contracts": "2.0.0-alpha.55",
|
|
54
|
+
"openxiangda-devkit-core": "2.0.0-alpha.72",
|
|
55
|
+
"openxiangda-mcp": "2.0.0-alpha.72",
|
|
56
|
+
"openxiangda-nest": "2.0.0-alpha.66",
|
|
57
|
+
"openxiangda-skill-kit": "2.0.0-alpha.90",
|
|
58
58
|
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
package/skills/manifest.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
{
|
|
5
5
|
"name": "openxiangda-v2",
|
|
6
6
|
"description": "Use when researching, designing, building, testing, or delivering a complete OpenXiangda 2.0 application.",
|
|
7
|
-
"sha256": "
|
|
7
|
+
"sha256": "98417ad9a7d8f02cc88435d4642ba12f345dee9f9e455133efe3b124e40fdb75"
|
|
8
8
|
}
|
|
9
9
|
]
|
|
10
10
|
}
|
|
@@ -10,14 +10,14 @@ Treat requirement discovery, architecture, authorization, development, testing a
|
|
|
10
10
|
Before a workspace exists, use this Skill's exact npm version:
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
pnpm dlx openxiangda@2.0.0-alpha.
|
|
14
|
-
pnpm dlx openxiangda@2.0.0-alpha.
|
|
13
|
+
pnpm dlx openxiangda@2.0.0-alpha.27 login --base-url <platform>
|
|
14
|
+
pnpm dlx openxiangda@2.0.0-alpha.27 create <directory>
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
Inside an application, use only its locked executable through `pnpm openxiangda`. Never invoke a bare global `openxiangda`, because that executable may belong to stable 1.x. Moving tags such as `latest` and `alpha` are forbidden. To install or refresh this same Skill from the package, run:
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
pnpm dlx openxiangda@2.0.0-alpha.
|
|
20
|
+
pnpm dlx openxiangda@2.0.0-alpha.27 skill install --force
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
Use this order:
|
|
@@ -7,13 +7,96 @@ Keep normal record CRUD in the platform Data API. Use `apps/server` only for typ
|
|
|
7
7
|
|
|
8
8
|
Every interactive business action uses `@OpenXiangdaOperation(operation)`. The
|
|
9
9
|
guard checks `operation.requiredCapability` once at App API ingress. Inside that
|
|
10
|
-
declared action, inject `OpenXiangdaBusinessDataApiService
|
|
11
|
-
`
|
|
10
|
+
declared action, inject `OpenXiangdaBusinessDataApiService`,
|
|
11
|
+
`OpenXiangdaBusinessNotificationService`, or use
|
|
12
|
+
`OpenXiangdaStandardOperations`: Native Data and Notification Hub then run as the trusted backend
|
|
12
13
|
for this exact application, environment, version and operation. Do not forward
|
|
13
14
|
the caller's resource, row or field permissions into that internal Data call,
|
|
14
15
|
and do not author an `authorizationJSON` permission mirror. The platform still
|
|
15
16
|
records the initiating user and action code in records, files, events and audit.
|
|
16
17
|
|
|
18
|
+
For an informational business notification, inject
|
|
19
|
+
`OpenXiangdaBusinessNotificationService` in the same declared action. The SDK
|
|
20
|
+
uses the short-lived gateway invocation, never the caller's original login
|
|
21
|
+
token. The platform rechecks the operation and capability, promotes the call to
|
|
22
|
+
the exact application/environment principal, and records the initiating user
|
|
23
|
+
and action. Do not grant ordinary users `app:notification2:send` and do not use
|
|
24
|
+
the privileged `OpenXiangdaNotificationService` as an application workaround.
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { Inject } from '@nestjs/common';
|
|
28
|
+
import {
|
|
29
|
+
OPENXIANGDA_NOTIFICATION_BUSINESS_SEND_V2,
|
|
30
|
+
OPENXIANGDA_NOTIFICATION_EVENT_SEND_V2,
|
|
31
|
+
} from 'openxiangda/contracts';
|
|
32
|
+
import {
|
|
33
|
+
OpenXiangdaBusinessNotificationService,
|
|
34
|
+
} from 'openxiangda/nest';
|
|
35
|
+
|
|
36
|
+
constructor(
|
|
37
|
+
@Inject(OpenXiangdaBusinessNotificationService)
|
|
38
|
+
private readonly notifications: OpenXiangdaBusinessNotificationService,
|
|
39
|
+
) {}
|
|
40
|
+
|
|
41
|
+
await this.notifications.send({
|
|
42
|
+
schemaVersion: OPENXIANGDA_NOTIFICATION_BUSINESS_SEND_V2,
|
|
43
|
+
eventId: body.eventId,
|
|
44
|
+
correlationId: `proposal:${proposal.id}`,
|
|
45
|
+
messageKey: `proposal:${proposal.id}:invite:${member.id}`,
|
|
46
|
+
sourceSequence: proposal.revision,
|
|
47
|
+
recipients: [{ userId: member.userId }],
|
|
48
|
+
title: '待您附议',
|
|
49
|
+
summary: proposal.title,
|
|
50
|
+
navigationTarget: {
|
|
51
|
+
kind: 'APP_ROUTE',
|
|
52
|
+
appCode: 'proposal_app',
|
|
53
|
+
routeCode: 'proposal.detail',
|
|
54
|
+
pathParams: { id: proposal.id },
|
|
55
|
+
access: 'AUTHENTICATED',
|
|
56
|
+
},
|
|
57
|
+
idempotencyKey: `proposal:${proposal.id}:invite:${member.id}:v${proposal.revision}`,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The fixed template accepts only `title` and optional `summary`. Reuse the same
|
|
63
|
+
`eventId` or `idempotencyKey` for retries. Reuse `messageKey` with increasing
|
|
64
|
+
`sourceSequence` for state convergence; do not generate a new logical message
|
|
65
|
+
for each retry.
|
|
66
|
+
|
|
67
|
+
The generated
|
|
68
|
+
`notificationTemplateCodes.applicationInformational` constant documents the
|
|
69
|
+
selected platform template; `send()` chooses it automatically and does not
|
|
70
|
+
accept a caller-supplied template code.
|
|
71
|
+
|
|
72
|
+
Inside a signed Application Events/date-trigger handler, call
|
|
73
|
+
`sendFromEvent()` on the same service. The SDK obtains the application
|
|
74
|
+
credential and forwards the current eventId, deliveryId and subscription code.
|
|
75
|
+
Declare only dot paths beneath the immutable event `data`; Notification Hub
|
|
76
|
+
resolves the actual Native user IDs and presentation text. Do not copy values
|
|
77
|
+
from the event into a caller-supplied `recipients` array and never manufacture a
|
|
78
|
+
user token.
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
await this.notifications.sendFromEvent({
|
|
82
|
+
schemaVersion: OPENXIANGDA_NOTIFICATION_EVENT_SEND_V2,
|
|
83
|
+
correlationId: `proposal:${event.data.proposalId}`,
|
|
84
|
+
messageKey: `proposal:${event.data.proposalId}:reminder`,
|
|
85
|
+
sourceSequence: event.data.revision,
|
|
86
|
+
recipientPaths: ['assigneeUserIds'],
|
|
87
|
+
titlePath: 'notification.title',
|
|
88
|
+
summaryPath: 'notification.summary',
|
|
89
|
+
navigationTarget: {
|
|
90
|
+
kind: 'APP_ROUTE',
|
|
91
|
+
appCode: 'proposal_app',
|
|
92
|
+
routeCode: 'proposal.detail',
|
|
93
|
+
pathParams: { id: event.data.proposalId },
|
|
94
|
+
access: 'AUTHENTICATED',
|
|
95
|
+
},
|
|
96
|
+
idempotencyKey: event.id,
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
17
100
|
`OpenXiangdaDataApiService` deliberately retains ordinary current-user Data
|
|
18
101
|
authorization and automatically inherits the request Perspective for reads.
|
|
19
102
|
Its writes still authorize against the complete role union. Do not use it to
|
|
@@ -11,6 +11,7 @@ Use these optional modules only when the application has a real standard approva
|
|
|
11
11
|
- Workflow Kernel v2 owns definitions, instances, tasks, participants, commands, transitions and audit facts.
|
|
12
12
|
- Application Events v2 owns durable facts and delivery.
|
|
13
13
|
- Notification Hub v2 owns templates, rules, logical messages, channel delivery, callbacks and message operations.
|
|
14
|
+
- Named Action business notifications use `OpenXiangdaBusinessNotificationService` and the platform-owned `application.informational.standard` template. App Gateway authorizes the current user once; Notification Hub revalidates the action proof, sends as the application principal, and retains initiating user/action audit. Ordinary users never need `app:notification2:send`.
|
|
14
15
|
- Native Identity/AuthZ v2 owns the current user and the union of that user's current application roles. Perspective is read-only and never changes workflow participation or action authorization.
|
|
15
16
|
- Never import, query, migrate or call 1.x workflow/message code, tables, APIs, queues, templates or callbacks.
|
|
16
17
|
|
|
@@ -47,6 +48,22 @@ A node may reference a notification profile that selects:
|
|
|
47
48
|
|
|
48
49
|
Template variables must be declared by JSON Schema and stay within the field policy visible to the recipient. The Notification Hub does not query arbitrary application tables to complete a template.
|
|
49
50
|
|
|
51
|
+
For a non-Workflow informational message, the public business contract accepts
|
|
52
|
+
only `title`, optional `summary`, recipients and a canonical navigation target.
|
|
53
|
+
Supply stable `eventId`, `idempotencyKey`, `messageKey` and monotonic
|
|
54
|
+
`sourceSequence`: duplicate events and idempotency keys replay the stored
|
|
55
|
+
message, while a later source sequence converges the same logical message.
|
|
56
|
+
Never forward a user token, application credential or global Notification Hub
|
|
57
|
+
permission from application code.
|
|
58
|
+
|
|
59
|
+
A signed event/date-trigger consumer uses
|
|
60
|
+
`OpenXiangdaBusinessNotificationService.sendFromEvent()`. The application
|
|
61
|
+
declares safe paths under event `data` for recipients, title and summary;
|
|
62
|
+
Notification Hub verifies the active durable delivery and resolves those paths
|
|
63
|
+
itself. The audit actor remains the application event consumer with eventId,
|
|
64
|
+
deliveryId and subscription code as initiating source. Missing or forged event
|
|
65
|
+
proof, arbitrary recipient values and user impersonation are rejected.
|
|
66
|
+
|
|
50
67
|
## Detail navigation
|
|
51
68
|
|
|
52
69
|
Use a canonical navigation target with `PLATFORM_ROUTE`, `APP_ROUTE` or allowlisted `EXTERNAL_URL`, stable route code, path/query parameters and an authenticated access requirement. Do not place environment domains, bearer tokens, cookies, identity-switching credentials or secrets in template strings.
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
- Never write resource-level `schemaVersion`, `appCode`, `schema`, `surface`, `capabilities`, `fieldPolicies` or `platform/data` modules. The compiler derives the strict DataResource, CRUD capabilities, Surface and AI Schema. The application manifest still starts with its one top-level `schemaVersion: 3`.
|
|
9
9
|
- Ordinary list/get/create/update/delete, filters, export and batch operations use the platform Native Data API. Do not create Function CRUD or NestJS wrappers.
|
|
10
10
|
- Add NestJS only for a named business action that needs a cross-resource transaction, an invariant or an external side effect.
|
|
11
|
-
- Every interactive business action binds `@OpenXiangdaOperation(operation)` and injects `OpenXiangdaBusinessDataApiService` or `OpenXiangdaStandardOperations`. The platform checks the action capability once at App API ingress; the trusted backend then has full Data access only to its exact application/environment while audit retains the initiating user. Do not author `authorizationJSON` or reapply the user's resource, row and field permissions inside the action.
|
|
11
|
+
- Every interactive business action binds `@OpenXiangdaOperation(operation)` and injects `OpenXiangdaBusinessDataApiService`, `OpenXiangdaBusinessNotificationService`, or `OpenXiangdaStandardOperations`. The platform checks the action capability once at App API ingress; the trusted backend then has full Data/managed business-notification access only to its exact application/environment while audit retains the initiating user and action. Do not author `authorizationJSON`, forward user tokens, grant ordinary users `app:notification2:send`, or reapply the user's resource, row and field permissions inside the action.
|
|
12
12
|
- A NestJS backend declares only `enabled`, `isolation: 'shared' | 'dedicated'` and `resourceProfile: 'light' | 'standard'`. Never put raw Kubernetes resources, replicas, ports or environment maps in application metadata; the platform owns capacity and scaling.
|
|
13
13
|
- Use the current logged-in user and the union of that user's application roles. An optional declared Perspective projects only read visibility (pages, rows and fields); create/update/delete, workflows and custom actions continue to authorize against the complete union. Standard Data API calls inherit `X-OpenXiangda-Perspective` automatically. Use `@CurrentPerspective()` only when custom Nest code reads outside the standard Data API, and apply an equivalent read projection explicitly. Business code must not persist a platform Token or authorization result and must not implement a second identity path.
|
|
14
14
|
- Fields inherit the resource read/create/update capabilities. Use field `access` only to tighten them; arrays are all-of and `false` is explicit deny. There is no `write` fallback.
|