openxiangda-skill-kit 2.0.0-alpha.79 → 2.0.0-alpha.80
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/package.json +2 -2
- package/skills/openxiangda-v2/references/backend.md +31 -7
- package/skills/openxiangda-v2/references/data-authz.md +1 -1
- package/skills/openxiangda-v2/references/delivery.md +17 -1
- package/skills/openxiangda-v2/references/testing.md +37 -2
- package/skills/openxiangda-v2/references/workspace.md +4 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openxiangda-skill-kit",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.80",
|
|
4
4
|
"description": "Validation and deterministic packaging for OpenXiangda 2.0 AI skills.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"README.md"
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"openxiangda-devkit-core": "2.0.0-alpha.
|
|
20
|
+
"openxiangda-devkit-core": "2.0.0-alpha.62"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"tsx": "4.23.12",
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
# OpenXiangda 2.0 Backend
|
|
2
2
|
|
|
3
|
-
Keep normal record CRUD in the platform Data API. Use `apps/server` only for typed business actions that need server-side logic. For an interactive request, the platform gateway supplies the verified current user, complete application-role union and capabilities
|
|
3
|
+
Keep normal record CRUD in the platform Data API. Use `apps/server` only for typed business actions that need server-side logic. For an interactive request, the platform gateway supplies the verified current user, complete application-role union and capabilities. Controllers bind operations and capabilities through `openxiangda/nest`; workers continue to use their explicit application identity.
|
|
4
|
+
|
|
5
|
+
Every interactive business action uses `@OpenXiangdaOperation(operation)`. The
|
|
6
|
+
guard checks `operation.requiredCapability` once at App API ingress. Inside that
|
|
7
|
+
declared action, inject `OpenXiangdaBusinessDataApiService` or use
|
|
8
|
+
`OpenXiangdaStandardOperations`: Native Data then runs as the trusted backend
|
|
9
|
+
for this exact application, environment, version and operation. Do not forward
|
|
10
|
+
the caller's resource, row or field permissions into that internal Data call,
|
|
11
|
+
and do not author an `authorizationJSON` permission mirror. The platform still
|
|
12
|
+
records the initiating user and action code in records, files, events and audit.
|
|
13
|
+
|
|
14
|
+
`OpenXiangdaDataApiService` deliberately retains ordinary current-user Data
|
|
15
|
+
authorization. Do not use it to implement a declared business action. The
|
|
16
|
+
business facade also rejects routes without immutable `OpenXiangdaOperation`
|
|
17
|
+
metadata, so a controller cannot silently gain trusted Data access.
|
|
4
18
|
|
|
5
19
|
Do not duplicate resource persistence in controllers. Keep actions bounded and side-effect behavior explicit. Run `pnpm openxiangda dev` for the connected loop and `pnpm openxiangda check` before delivery.
|
|
6
20
|
|
|
@@ -16,15 +30,25 @@ Every constructor dependency in a `@Controller` or `@Injectable` class uses an
|
|
|
16
30
|
explicit token:
|
|
17
31
|
|
|
18
32
|
```ts
|
|
19
|
-
import { Controller, Inject } from '@nestjs/common';
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
|
|
33
|
+
import { Controller, Inject, Post } from '@nestjs/common';
|
|
34
|
+
import { appOperations } from '@app/contracts';
|
|
35
|
+
import {
|
|
36
|
+
OpenXiangdaBusinessDataApiService,
|
|
37
|
+
OpenXiangdaOperation,
|
|
38
|
+
} from 'openxiangda/nest';
|
|
39
|
+
|
|
40
|
+
@Controller()
|
|
23
41
|
export class VisitorReservationsController {
|
|
24
42
|
constructor(
|
|
25
|
-
@Inject(
|
|
26
|
-
private readonly
|
|
43
|
+
@Inject(OpenXiangdaBusinessDataApiService)
|
|
44
|
+
private readonly data: OpenXiangdaBusinessDataApiService,
|
|
27
45
|
) {}
|
|
46
|
+
|
|
47
|
+
@Post('/api/reservations/enroll')
|
|
48
|
+
@OpenXiangdaOperation(appOperations.reservationEnroll)
|
|
49
|
+
async enroll() {
|
|
50
|
+
return await this.data.create('visitor-reservations', { status: 'pending' });
|
|
51
|
+
}
|
|
28
52
|
}
|
|
29
53
|
```
|
|
30
54
|
|
|
@@ -65,7 +65,7 @@ without `access` inherits the resource read/create/update capability. Each
|
|
|
65
65
|
access array is all-of; `false` is explicit deny. The same arrays drive the
|
|
66
66
|
generated UI and platform field policies.
|
|
67
67
|
|
|
68
|
-
Field types are semantic, not PostgreSQL storage aliases. Use the catalog in the generated `AGENTS.md`: for example `text.short`, `number.integer`, `user.single`, `department.multiple`, `resource-ref.single`, `file`, `address` and `subtable`. The compiler alone chooses storage columns and constraints. Reference fields store
|
|
68
|
+
Field types are semantic, not PostgreSQL storage aliases. Use the catalog in the generated `AGENTS.md`: for example `text.short`, `number.integer`, `user.single`, `department.multiple`, `resource-ref.single`, `file`, `address` and `subtable`. The compiler alone chooses storage columns and constraints. Reference fields store JSON display values. For `resource-ref.*`, `resourceCode`, `value`, `label`, optional `description` and optional `snapshot` are convenient historical display data only: the target resource remains authoritative, the platform does not create a foreign key or refresh/check the stored JSON, and business actions that need current target state must query it by `resourceCode` plus `value`. A resource source `labelField` must point to `text.short` or `text.long`; a `serial-number` field can be listed in `searchFields`, `descriptionFields` or `snapshotFields`, but it is not a display label. File limits exist only under `file`; `maxCount` owns the single/multiple bound and `maxSizeMb` owns the per-file size bound. There is no `file.multiple` key.
|
|
69
69
|
|
|
70
70
|
Do not author raw schema or storage words as field types. `string`, `text`,
|
|
71
71
|
`integer`, `decimal`, `boolean`, `date`, `datetime`, `uuid`, `json` and `file`
|
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
# OpenXiangda 2.0 Delivery
|
|
2
2
|
|
|
3
|
-
Run `pnpm openxiangda check`; it owns generation, static checks, tests
|
|
3
|
+
Run `pnpm openxiangda check --json`; it owns generation, static checks, tests
|
|
4
|
+
and production builds but deliberately does not seal an AppPackage. Its
|
|
5
|
+
`data.sealedArtifact` object and `.openxiangda/build/seal-status.json` make that
|
|
6
|
+
state explicit even when an older `app-package.json` remains on disk. Deploy to
|
|
7
|
+
test with the returned `openxiangda deploy` next command. Deploy owns the
|
|
8
|
+
official application Dockerfile and platform-provided repository target,
|
|
9
|
+
builds and pushes the Nest image, then writes a `sealed` status tied to the new
|
|
10
|
+
immutable package digest. Never ask the developer for an image tag, digest,
|
|
11
|
+
registry password, Docker configuration, or another public build command. If
|
|
12
|
+
Docker, Buildx, repository configuration, or registry login is missing,
|
|
13
|
+
preserve the stable machine error and retry with the same
|
|
14
|
+
`pnpm openxiangda deploy` command after fixing that prerequisite.
|
|
15
|
+
|
|
16
|
+
`pnpm openxiangda accept --plan <file>` is an optional manual preproduction
|
|
17
|
+
test helper. It prepares expiring real identities but does not deploy, seal,
|
|
18
|
+
promote or satisfy any release gate. Use it only when the requested acceptance
|
|
19
|
+
needs real role membership and browser login.
|
|
4
20
|
|
|
5
21
|
Use `pnpm openxiangda status` and `pnpm openxiangda logs` without an ID for the most recent run, or pass an explicit run ID.
|
|
6
22
|
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# Testing and Acceptance
|
|
2
2
|
|
|
3
|
-
Run `pnpm openxiangda check` after declaration or code changes. It owns
|
|
3
|
+
Run `pnpm openxiangda check --json` after declaration or code changes. It owns
|
|
4
|
+
generation, static validation, unit tests and production builds; preserve its
|
|
5
|
+
stable diagnostic instead of bypassing a failing stage. Read
|
|
6
|
+
`data.sealedArtifact` in the machine result. A successful check always reports
|
|
7
|
+
`state: "check-did-not-seal"`, `sealed: false` and
|
|
8
|
+
`usableForDeploy: false`; it may also describe an older package as
|
|
9
|
+
`previousArtifact`. Never treat an existing `.openxiangda/build/app-package.json`
|
|
10
|
+
as output from the current check. Follow the exact `nextCommand`: rerun check
|
|
11
|
+
when diagnostics fail, or run `openxiangda deploy` to build, seal and deploy.
|
|
4
12
|
|
|
5
13
|
For each changed resource, verify the real chain:
|
|
6
14
|
|
|
@@ -11,6 +19,33 @@ For each changed resource, verify the real chain:
|
|
|
11
19
|
5. stored values and audit records match the declared shape;
|
|
12
20
|
6. PostgreSQL/RLS remains authoritative, including current-user and multi-role-union cases.
|
|
13
21
|
|
|
14
|
-
Mock and unit tests are useful but do not close remote acceptance.
|
|
22
|
+
Mock and unit tests are useful but do not close remote acceptance. When real
|
|
23
|
+
identity acceptance is needed, create a short-lived local plan and run:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pnpm openxiangda accept --plan .openxiangda/acceptance-plan.json --json
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The plan is explicit and preproduction-only:
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"schemaVersion": "openxiangda.preproduction-acceptance-plan/v2",
|
|
34
|
+
"environmentKey": "preproduction",
|
|
35
|
+
"expiresInMinutes": 240,
|
|
36
|
+
"actors": [
|
|
37
|
+
{ "key": "allowed", "roleCodes": ["resource_admin"] },
|
|
38
|
+
{ "key": "denied", "roleCodes": ["resource_viewer"] }
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The result returns real temporary users and one-time login URLs. Treat those
|
|
44
|
+
URLs as secrets, do not commit the plan/result, and let them expire. `accept`
|
|
45
|
+
is an additional manual test facility: it is never called by `check` or
|
|
46
|
+
`deploy`, never becomes a release gate, and a skipped run must not block a
|
|
47
|
+
release. When it is used, capture the exact AppVersion, environment Head,
|
|
48
|
+
positive/negative result, browser behavior and request identifiers. Production
|
|
49
|
+
promotion reuses the exact successful version; it is not another build.
|
|
15
50
|
|
|
16
51
|
For a new toolchain release, also create a completely fresh workspace using only the packed or published `openxiangda` package. Do not use repository-relative imports, unpublished workspace links or machine-installed legacy Skills.
|
|
@@ -6,16 +6,17 @@
|
|
|
6
6
|
- 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`.
|
|
7
7
|
- 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.
|
|
8
8
|
- Add NestJS only for a named business action that needs a cross-resource transaction, an invariant or an external side effect.
|
|
9
|
+
- 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.
|
|
9
10
|
- 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.
|
|
10
11
|
- Use the current logged-in user and the union of that user's application roles. The generated client uses same-origin cookies and does not transmit a RoleSession header. Business code must not persist a platform Token or authorization result and must not implement a second identity path.
|
|
11
12
|
- 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.
|
|
12
13
|
- Field `type` is semantic, never a hand-authored database type. The supported catalog is exactly `text.short`, `text.long`, `text.rich`, `number.integer`, `number.decimal`, `boolean`, `date`, `time`, `datetime`, `date-range`, `datetime-range`, `option.single`, `option.multiple`, `cascade.single`, `cascade.multiple`, `user.single`, `user.multiple`, `department.single`, `department.multiple`, `resource-ref.single`, `resource-ref.multiple`, `file`, `image`, `signature`, `address`, `location`, `json`, `serial-number`, `uuid` and `subtable`. The compiler alone derives PostgreSQL columns, constraints and indexes.
|
|
13
14
|
- Declare every custom operation capability in `authz.capabilities` with `kind: 'backend'`, then reference that same code from the operation and its allowed roles. Generated resource CRUD capabilities do not go in this catalog.
|
|
14
15
|
- Visitor duplicate protection uses `createVisitorReservation({ duplicateMatch: { fieldCode: submittedValue }, ... })`. `duplicateMatch` is a non-empty value map, never a field-name array, and no mutable pre-read is allowed.
|
|
15
|
-
- Desktop and mobile pages share values, validation and authorization, but use separate renderers. Options, members
|
|
16
|
-
- `option.*`, `user.*`, `department.*` and `resource-ref.*` values never collapse to scalar IDs. Single values store one labeled
|
|
16
|
+
- Desktop and mobile pages share values, validation and authorization, but use separate renderers. Options, members and departments store display snapshots; resource references store direct JSON display values; attachments, images and signatures use platform-managed file references.
|
|
17
|
+
- `option.*`, `user.*`, `department.*` and `resource-ref.*` values never collapse to scalar IDs. Single values store one labeled object and multiple values store object arrays. `resource-ref.*` JSON is not a foreign key, trusted target snapshot or automatically refreshed copy; current target state is read by `resourceCode` plus `value`. A resource source `labelField` must be `text.short` or `text.long`; `serial-number` is allowed in source search, description and snapshot fields, but not as the label. `location` accepts only exact WGS84 coordinates captured by DingTalk or browser geolocation; it has no manual input or `manual` source. Roles that consume directory-backed fields explicitly include `app:<app-code>:directory:read`.
|
|
17
18
|
- Derive role grants with `resourceCapabilityCodes(appCode, resourceCode)`. Declare current-user rows only with `currentUserDataPolicy(...)`; do not invent operators, values or alternate current-user spellings.
|
|
18
19
|
- Do not add compatibility aliases, migration branches or silent fallbacks for an earlier 2.0 alpha contract. Replace an incorrect contract and regenerate the application.
|
|
19
20
|
- Standard Workflow and Notification Hub are optional 2.0 modules. Enable them only through the canonical `openxiangda.config.ts` declarations and generated clients; never copy 1.x workflow/message code, tables, APIs, templates or callbacks into this workspace. Keep ordinary CRUD and application-specific state machines independent of them.
|
|
20
|
-
- Run `pnpm openxiangda check` after contract changes. Deploy with `pnpm openxiangda deploy`, inspect with `pnpm openxiangda status` and `pnpm openxiangda logs`, and use the platform rollback command rather than mutating K3s directly.
|
|
21
|
+
- Run `pnpm openxiangda check --json` after contract changes and read `data.sealedArtifact`; check never seals, and an older `.openxiangda/build/app-package.json` is not the current check result. Use `pnpm openxiangda accept --plan <file>` only for optional real preproduction identity acceptance; it never blocks delivery. Deploy with `pnpm openxiangda deploy`, inspect with `pnpm openxiangda status` and `pnpm openxiangda logs`, and use the platform rollback command rather than mutating K3s directly.
|
|
21
22
|
- AI-native clients start the workspace protocol through the same pinned binary: `pnpm exec openxiangda --mcp-stdio --cwd <workspace>`. Read `openxiangda://workspace/contracts` or call `contract_describe`, and require its `aiCatalog` and `aiCatalogDigest` to match the normal compiler output. This is a stdio transport mode, not a ninth CLI command. Never write an application MCP server, Catalog file, preview store or second authorization path.
|