create-windy 0.3.4 → 0.3.6

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.
Files changed (101) hide show
  1. package/README.md +20 -3
  2. package/dist/cli.js +585 -111
  3. package/package.json +1 -1
  4. package/template/.windy-template.json +2 -2
  5. package/template/AGENTS.md +4 -0
  6. package/template/README.md +18 -11
  7. package/template/apps/server/src/application-services.ts +16 -0
  8. package/template/apps/server/src/data-governance/export/authorization-port.test.ts +5 -1
  9. package/template/apps/server/src/data-governance/export/drizzle-repository.integration.test.ts +2 -0
  10. package/template/apps/server/src/data-governance/export/drizzle-repository.ts +1 -0
  11. package/template/apps/server/src/data-governance/export/job-runtime.test.ts +3 -1
  12. package/template/apps/server/src/data-governance/export/job-runtime.ts +53 -14
  13. package/template/apps/server/src/data-governance/export/ndjson-stream.ts +8 -0
  14. package/template/apps/server/src/data-governance/export/postgres-recovery.integration.test.ts +2 -0
  15. package/template/apps/server/src/data-governance/export/renderer-job-runtime.test.ts +235 -0
  16. package/template/apps/server/src/data-governance/export/renderer-runtime.ts +293 -0
  17. package/template/apps/server/src/data-governance/export/renderer-selection.test.ts +67 -0
  18. package/template/apps/server/src/data-governance/export/repository.test.ts +2 -0
  19. package/template/apps/server/src/data-governance/export/request-fingerprint.test.ts +13 -0
  20. package/template/apps/server/src/data-governance/export/request-fingerprint.ts +2 -0
  21. package/template/apps/server/src/data-governance/export/routes.ts +11 -1
  22. package/template/apps/server/src/data-governance/export/service-support.ts +61 -4
  23. package/template/apps/server/src/data-governance/export/service.ts +8 -2
  24. package/template/apps/server/src/data-governance/export/types.ts +27 -0
  25. package/template/apps/server/src/index.ts +1 -0
  26. package/template/apps/server/src/jobs/artifact-service.test.ts +14 -2
  27. package/template/apps/server/src/jobs/artifact-service.ts +10 -0
  28. package/template/apps/server/src/jobs/drizzle-execution-repository.ts +17 -18
  29. package/template/apps/server/src/jobs/drizzle-execution.integration.test.ts +19 -1
  30. package/template/apps/server/src/jobs/drizzle-mappers.ts +3 -1
  31. package/template/apps/server/src/jobs/drizzle-recovery-repository.ts +49 -2
  32. package/template/apps/server/src/jobs/execution-repository.ts +17 -0
  33. package/template/apps/server/src/jobs/in-memory-control.ts +135 -0
  34. package/template/apps/server/src/jobs/in-memory-execution.ts +34 -65
  35. package/template/apps/server/src/jobs/worker.ts +27 -3
  36. package/template/apps/server/src/module-host/governed-export-route-support.ts +24 -5
  37. package/template/apps/server/src/module-host/governed-export-routes.test.ts +5 -1
  38. package/template/apps/server/src/module-host/governed-export-routes.ts +1 -2
  39. package/template/apps/server/src/module-host/governed-renderer-registration.test.ts +247 -0
  40. package/template/apps/server/src/module-host/governed-resources.test.ts +1 -0
  41. package/template/apps/server/src/module-host/governed-resources.ts +56 -0
  42. package/template/apps/server/src/module-host/http-runtime.ts +3 -0
  43. package/template/apps/server/src/module-host/job-port.test.ts +262 -0
  44. package/template/apps/server/src/module-host/job-port.ts +334 -0
  45. package/template/apps/server/src/module-host/request-context.ts +14 -26
  46. package/template/apps/server/src/module-host/route-installer.ts +11 -0
  47. package/template/apps/web/src/app/business-routes.ts +22 -0
  48. package/template/apps/web/src/components/common/AccessSnapshotBoundary.vue +112 -0
  49. package/template/apps/web/src/components/common/AccessSnapshotBoundary.webtest.ts +130 -0
  50. package/template/apps/web/src/components/common/AccessSnapshotNotice.vue +117 -0
  51. package/template/apps/web/src/composables/access-snapshot-change.ts +131 -0
  52. package/template/apps/web/src/composables/access-snapshot-change.webtest.ts +103 -0
  53. package/template/apps/web/src/composables/useAccessSnapshot.ts +48 -2
  54. package/template/apps/web/src/composables/useAccessSnapshot.webtest.ts +54 -0
  55. package/template/apps/web/src/composables/useAccessSnapshotMonitor.ts +42 -0
  56. package/template/apps/web/src/layout/AppShell.vue +28 -25
  57. package/template/apps/web/src/layout/AppShell.webtest.ts +1 -0
  58. package/template/apps/web/src/router/business-routes.ts +68 -0
  59. package/template/apps/web/src/router/business-routes.webtest.ts +85 -0
  60. package/template/apps/web/src/router/index.ts +7 -0
  61. package/template/apps/web/src/router/shared-scaffold-neutrality.webtest.ts +12 -0
  62. package/template/apps/web/src/services/access-api.ts +5 -1
  63. package/template/apps/web/src/services/access-api.webtest.ts +35 -0
  64. package/template/docs/architecture/ai-egress.md +12 -9
  65. package/template/docs/architecture/durable-jobs.md +7 -1
  66. package/template/docs/architecture/foundation-infrastructure.md +163 -0
  67. package/template/docs/architecture/module-host.md +115 -0
  68. package/template/docs/architecture/server-module-interface.md +39 -0
  69. package/template/docs/architecture/web-access-snapshot-resilience.md +60 -0
  70. package/template/docs/development/business-web-routes.md +66 -0
  71. package/template/docs/development/custom-login-page.md +3 -3
  72. package/template/docs/development/module-lifecycle.md +71 -0
  73. package/template/docs/operations/observability.md +5 -1
  74. package/template/docs/platform/agent-runtime.md +6 -6
  75. package/template/docs/platform/agent-tool-sandbox.md +58 -0
  76. package/template/docs/platform/document-ai-runtime.md +204 -0
  77. package/template/docs/platform/governed-export-renderers.md +132 -0
  78. package/template/docs/platform/navigation-registry.md +5 -0
  79. package/template/docs/platform/organization-membership.md +2 -1
  80. package/template/docs/platform/speech-ai-runtime.md +156 -0
  81. package/template/docs/platform/system-crud-api.md +7 -1
  82. package/template/docs/platform/vision-ai-runtime.md +97 -0
  83. package/template/docs/platform/web-system-crud.md +6 -0
  84. package/template/packages/config/package.json +1 -1
  85. package/template/packages/database/drizzle/0042_puzzling_rumiko_fujikawa.sql +27 -0
  86. package/template/packages/database/drizzle/meta/0042_snapshot.json +8541 -0
  87. package/template/packages/database/drizzle/meta/_journal.json +7 -0
  88. package/template/packages/database/package.json +1 -1
  89. package/template/packages/database/src/schema/durable-jobs.ts +1 -0
  90. package/template/packages/database/src/schema/governed-exports.ts +15 -0
  91. package/template/packages/database/src/schema-governed-exports.test.ts +21 -1
  92. package/template/packages/jobs/package.json +1 -1
  93. package/template/packages/jobs/src/handlers.ts +1 -0
  94. package/template/packages/jobs/src/types.ts +1 -0
  95. package/template/packages/modules/package.json +1 -1
  96. package/template/packages/server-sdk/index.ts +11 -0
  97. package/template/packages/server-sdk/package.json +1 -1
  98. package/template/packages/server-sdk/src/data-governance-registration.ts +46 -0
  99. package/template/packages/server-sdk/src/jobs-port.ts +69 -0
  100. package/template/packages/server-sdk/src/request-context.ts +2 -2
  101. package/template/packages/shared/package.json +1 -1
@@ -295,6 +295,13 @@
295
295
  "when": 1785102272102,
296
296
  "tag": "0041_yummy_prowler",
297
297
  "breakpoints": true
298
+ },
299
+ {
300
+ "idx": 42,
301
+ "version": "7",
302
+ "when": 1785151819729,
303
+ "tag": "0042_puzzling_rumiko_fujikawa",
304
+ "breakpoints": true
298
305
  }
299
306
  ]
300
307
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@southwind-ai/database",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "engines": {
@@ -205,6 +205,7 @@ export const durableJobArtifacts = pgTable(
205
205
  byteSize: integer("byte_size").notNull(),
206
206
  sha256: varchar("sha256", { length: 64 }).notNull(),
207
207
  ownerId: varchar("owner_id", { length: 64 }).notNull(),
208
+ metadata: jsonb("metadata").$type<Record<string, unknown>>(),
208
209
  expiresAt: timestamp("expires_at", { withTimezone: true }),
209
210
  createdAt: timestamp("created_at", { withTimezone: true })
210
211
  .notNull()
@@ -17,6 +17,18 @@ export interface GovernedExportQuerySnapshot {
17
17
  readonly [key: string]: JsonValue | undefined;
18
18
  }
19
19
 
20
+ export interface GovernedExportRendererSnapshot {
21
+ formatKey: string;
22
+ templateKey: string;
23
+ templateVersion: string;
24
+ inputSchemaKey: string;
25
+ contentType: string;
26
+ filenameExtension: string;
27
+ maxRecords: number;
28
+ maxOutputBytes: number;
29
+ timeoutSeconds: number;
30
+ }
31
+
20
32
  export const governedExportRequests = pgTable(
21
33
  "governed_export_requests",
22
34
  {
@@ -39,6 +51,9 @@ export const governedExportRequests = pgTable(
39
51
  querySnapshot: jsonb("query_snapshot")
40
52
  .$type<GovernedExportQuerySnapshot>()
41
53
  .notNull(),
54
+ renderer: jsonb("renderer")
55
+ .$type<GovernedExportRendererSnapshot>()
56
+ .notNull(),
42
57
  status: varchar("status", { length: 32 }).notNull(),
43
58
  approvalRequired: boolean("approval_required").notNull(),
44
59
  approvalId: varchar("approval_id", { length: 64 }),
@@ -1,6 +1,9 @@
1
1
  import { describe, expect, test } from "bun:test";
2
2
  import { getTableConfig } from "drizzle-orm/pg-core";
3
- import { governedExportRequests } from "./schema/index.js";
3
+ import {
4
+ durableJobArtifacts,
5
+ governedExportRequests,
6
+ } from "./schema/index.js";
4
7
 
5
8
  describe("governed export schema", () => {
6
9
  test("申请以 owner/resource/idempotency 唯一并受 Durable Job 外键约束", async () => {
@@ -9,6 +12,7 @@ describe("governed export schema", () => {
9
12
  expect(config.name).toBe("governed_export_requests");
10
13
  expect(governedExportRequests.scopeSnapshot.notNull).toBe(true);
11
14
  expect(governedExportRequests.requestFingerprint.notNull).toBe(true);
15
+ expect(governedExportRequests.renderer.notNull).toBe(true);
12
16
  expect(governedExportRequests.durableJobId.notNull).toBe(false);
13
17
  expect(config.foreignKeys[0]?.onDelete).toBe("restrict");
14
18
  expect(
@@ -45,5 +49,21 @@ describe("governed export schema", () => {
45
49
  expect(constraintMigration).toContain(
46
50
  'VALIDATE CONSTRAINT "ck_governed_exports_approval_job_state"',
47
51
  );
52
+ const rendererMigration = await Bun.file(
53
+ new URL(
54
+ "../drizzle/0042_puzzling_rumiko_fujikawa.sql",
55
+ import.meta.url,
56
+ ),
57
+ ).text();
58
+ expect(rendererMigration).toContain(
59
+ 'UPDATE "governed_export_requests"',
60
+ );
61
+ expect(rendererMigration).toContain(
62
+ 'ALTER COLUMN "renderer" SET NOT NULL',
63
+ );
64
+ expect(rendererMigration).toContain(
65
+ 'UPDATE "durable_job_artifacts" AS artifact',
66
+ );
67
+ expect(durableJobArtifacts.metadata.notNull).toBe(false);
48
68
  });
49
69
  });
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@southwind-ai/jobs",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "engines": {
@@ -25,6 +25,7 @@ export interface DurableHandlerContext {
25
25
  sha256: string;
26
26
  ownerId: string;
27
27
  expiresAt?: string;
28
+ metadata?: Record<string, unknown>;
28
29
  }): Promise<void>;
29
30
  }
30
31
 
@@ -110,6 +110,7 @@ export interface DurableJobArtifact {
110
110
  sha256: string;
111
111
  ownerId: string;
112
112
  expiresAt?: string;
113
+ metadata?: Record<string, unknown>;
113
114
  createdAt: string;
114
115
  }
115
116
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@southwind-ai/modules",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "engines": {
@@ -23,20 +23,31 @@ export type {
23
23
  ModuleAuditTarget,
24
24
  } from "./src/audit-port.js";
25
25
  export type {
26
+ ModuleJobCancelInput,
27
+ ModuleJobControlErrorCode,
28
+ ModuleJobPort,
29
+ ModuleJobProgressView,
30
+ ModuleJobRecoverInput,
31
+ ModuleJobStatus,
26
32
  ModuleJobSubmitter,
27
33
  ModuleJobSubmitInput,
28
34
  ModuleJobSubmitResult,
35
+ ModuleJobView,
29
36
  } from "./src/jobs-port.js";
37
+ export { ModuleJobControlError } from "./src/jobs-port.js";
30
38
  export type {
31
39
  ModuleDurableHandlerContext,
32
40
  ModuleDurableHandlerDefinition,
33
41
  ModuleDurableStoragePort,
34
42
  } from "./src/durable-handler.js";
35
43
  export type {
44
+ GovernedExportRenderedArtifact,
45
+ GovernedExportWatermarkContext,
36
46
  ModuleGovernedExportPage,
37
47
  ModuleGovernedExportPageInput,
38
48
  ModuleGovernedExportQuery,
39
49
  ModuleGovernedExportRegistration,
50
+ ModuleGovernedExportRendererRegistration,
40
51
  ModuleGovernedRecord,
41
52
  ModuleGovernedResourceContext,
42
53
  ModuleGovernedResourceRegistration,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@southwind-ai/server-sdk",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "engines": {
@@ -30,6 +30,47 @@ export interface ModuleGovernedExportPage {
30
30
  readonly nextCursor?: string;
31
31
  }
32
32
 
33
+ export interface GovernedExportWatermarkContext {
34
+ readonly actorId: string;
35
+ readonly generatedAt: string;
36
+ readonly scopeHash: string;
37
+ readonly jobId: string;
38
+ readonly requestId: string;
39
+ }
40
+
41
+ export interface GovernedExportRenderedArtifact {
42
+ readonly body: ReadableStream<Uint8Array>;
43
+ /** 不得包含记录原文或敏感字段,仅用于受控 artifact 元数据与审计。 */
44
+ readonly contentMetadata?: Readonly<Record<string, JsonValue>>;
45
+ }
46
+
47
+ export interface ModuleGovernedExportRendererRegistration {
48
+ readonly formatKey: string;
49
+ readonly templateKey: string;
50
+ readonly templateVersion: string;
51
+ readonly inputSchemaKey: string;
52
+ readonly contentType: string;
53
+ /** 不含点号,例如 pdf、docx、xlsx。 */
54
+ readonly filenameExtension: string;
55
+ readonly limits: {
56
+ readonly maxRecords: number;
57
+ readonly maxOutputBytes: number;
58
+ readonly timeoutSeconds: number;
59
+ };
60
+ render(
61
+ input: {
62
+ readonly records: AsyncIterable<Readonly<Record<string, JsonValue>>>;
63
+ readonly watermark: GovernedExportWatermarkContext;
64
+ },
65
+ context: {
66
+ readonly signal: AbortSignal;
67
+ readonly heartbeat: () => Promise<void>;
68
+ },
69
+ ):
70
+ | Promise<GovernedExportRenderedArtifact>
71
+ | GovernedExportRenderedArtifact;
72
+ }
73
+
33
74
  export interface ModuleGovernedExportRegistration {
34
75
  /** 四个导出端点的基路径,例如 /api/people/persons/exports。 */
35
76
  readonly basePath: string;
@@ -37,6 +78,11 @@ export interface ModuleGovernedExportRegistration {
37
78
  readonly approvalRequired?: boolean;
38
79
  /** 产物保留时间;宿主还会施加平台上限。 */
39
80
  readonly retentionSeconds?: number;
81
+ /**
82
+ * 服务端受治理 Renderer。声明后请求必须显式选择已注册 formatKey;
83
+ * 未声明时保持既有 NDJSON 行为。
84
+ */
85
+ readonly renderers?: readonly ModuleGovernedExportRendererRegistration[];
40
86
  validateQuery(query: unknown): ModuleGovernedExportQuery;
41
87
  readPage(
42
88
  input: ModuleGovernedExportPageInput,
@@ -22,3 +22,72 @@ export interface ModuleJobSubmitResult {
22
22
  export interface ModuleJobSubmitter {
23
23
  submit(input: ModuleJobSubmitInput): Promise<ModuleJobSubmitResult>;
24
24
  }
25
+
26
+ export type ModuleJobStatus =
27
+ | "queued"
28
+ | "running"
29
+ | "succeeded"
30
+ | "failed"
31
+ | "cancelled";
32
+
33
+ export interface ModuleJobProgressView {
34
+ readonly completedUnits: number;
35
+ readonly totalUnits?: number;
36
+ }
37
+
38
+ export interface ModuleJobView {
39
+ readonly jobId: string;
40
+ readonly handlerKey: string;
41
+ readonly status: ModuleJobStatus;
42
+ readonly progress?: ModuleJobProgressView;
43
+ readonly attempt: number;
44
+ readonly maxAttempts: number;
45
+ readonly createdAt: string;
46
+ readonly startedAt?: string;
47
+ readonly finishedAt?: string;
48
+ readonly failureCode?: string;
49
+ readonly canCancel: boolean;
50
+ readonly canRecover: boolean;
51
+ /** 当前持久化版本;控制操作必须回传该值以执行 CAS。 */
52
+ readonly version: string;
53
+ }
54
+
55
+ export interface ModuleJobCancelInput {
56
+ readonly jobId: string;
57
+ readonly reason: string;
58
+ readonly expectedStatus?: ModuleJobStatus;
59
+ readonly expectedVersion?: string;
60
+ }
61
+
62
+ export interface ModuleJobRecoverInput {
63
+ readonly jobId: string;
64
+ readonly reason: string;
65
+ readonly expectedAttempt: number;
66
+ readonly expectedStatus: ModuleJobStatus;
67
+ readonly expectedVersion: string;
68
+ }
69
+
70
+ export type ModuleJobControlErrorCode =
71
+ | "JOB_NOT_AVAILABLE"
72
+ | "JOB_STATE_CONFLICT"
73
+ | "JOB_CONTROL_UNAVAILABLE"
74
+ | "JOB_REASON_INVALID";
75
+
76
+ export class ModuleJobControlError extends Error {
77
+ constructor(
78
+ readonly code: ModuleJobControlErrorCode,
79
+ message: string,
80
+ ) {
81
+ super(message);
82
+ this.name = "ModuleJobControlError";
83
+ }
84
+ }
85
+
86
+ /**
87
+ * 宿主绑定 Module、Queue、Actor 与授权范围的 Durable Job 受限控制 Port。
88
+ */
89
+ export interface ModuleJobPort extends ModuleJobSubmitter {
90
+ get(jobId: string): Promise<ModuleJobView | undefined>;
91
+ cancel(input: ModuleJobCancelInput): Promise<ModuleJobView>;
92
+ recover(input: ModuleJobRecoverInput): Promise<ModuleJobView>;
93
+ }
@@ -2,7 +2,7 @@ import type { ModuleActor } from "./actor.js";
2
2
  import type { ModuleAuditEmitter } from "./audit-port.js";
3
3
  import type { ModuleAiArtifactPort } from "./ai-artifact-port.js";
4
4
  import type { ModuleAiOperationPort } from "./ai-operation-port.js";
5
- import type { ModuleJobSubmitter } from "./jobs-port.js";
5
+ import type { ModuleJobPort } from "./jobs-port.js";
6
6
  import type { ModuleStoragePort } from "./storage-port.js";
7
7
  import type { ModuleUserDirectoryPort } from "./user-directory-port.js";
8
8
 
@@ -21,7 +21,7 @@ export interface ModuleRequestContext {
21
21
  readonly audit: ModuleAuditEmitter;
22
22
  readonly aiArtifacts: ModuleAiArtifactPort;
23
23
  readonly aiOperations: ModuleAiOperationPort;
24
- readonly jobs: ModuleJobSubmitter;
24
+ readonly jobs: ModuleJobPort;
25
25
  readonly storage: ModuleStoragePort;
26
26
  readonly userDirectory: ModuleUserDirectoryPort;
27
27
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@southwind-ai/shared",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "engines": {