@carthooks/arcubase-cli 0.1.20 → 0.1.21

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 (36) hide show
  1. package/bundle/arcubase-admin.mjs +339 -51
  2. package/bundle/arcubase.mjs +339 -51
  3. package/dist/generated/command_registry.generated.d.ts +15 -0
  4. package/dist/generated/command_registry.generated.d.ts.map +1 -1
  5. package/dist/generated/command_registry.generated.js +21 -0
  6. package/dist/generated/help_examples.generated.d.ts +114 -0
  7. package/dist/generated/help_examples.generated.d.ts.map +1 -1
  8. package/dist/generated/help_examples.generated.js +155 -0
  9. package/dist/generated/type_index.generated.d.ts +4 -0
  10. package/dist/generated/type_index.generated.d.ts.map +1 -1
  11. package/dist/generated/type_index.generated.js +4 -0
  12. package/dist/generated/zod_registry.generated.d.ts +4 -1
  13. package/dist/generated/zod_registry.generated.d.ts.map +1 -1
  14. package/dist/generated/zod_registry.generated.js +4 -0
  15. package/dist/runtime/execute.d.ts.map +1 -1
  16. package/dist/runtime/execute.js +104 -31
  17. package/dist/runtime/zod_registry.d.ts.map +1 -1
  18. package/dist/runtime/zod_registry.js +8 -0
  19. package/package.json +1 -1
  20. package/sdk-dist/api/admin/ingress.ts +11 -0
  21. package/sdk-dist/docs/runtime-reference/access-rule.md +19 -0
  22. package/sdk-dist/docs/runtime-reference/help-examples/admin/access-rule/bulk-apply.json +105 -0
  23. package/sdk-dist/generated/command_registry.generated.ts +21 -0
  24. package/sdk-dist/generated/help_examples.generated.ts +155 -0
  25. package/sdk-dist/generated/type_index.generated.ts +4 -0
  26. package/sdk-dist/generated/zod_registry.generated.ts +6 -0
  27. package/sdk-dist/types/ingress.ts +31 -0
  28. package/src/generated/command_registry.generated.ts +21 -0
  29. package/src/generated/help_examples.generated.ts +155 -0
  30. package/src/generated/type_index.generated.ts +4 -0
  31. package/src/generated/zod_registry.generated.ts +6 -0
  32. package/src/runtime/execute.ts +159 -51
  33. package/src/runtime/zod_registry.ts +8 -0
  34. package/src/tests/command_registry.test.ts +1 -0
  35. package/src/tests/execute_validation.test.ts +86 -0
  36. package/src/tests/help.test.ts +13 -0
@@ -36,6 +36,161 @@ export const helpExamplesIndex = {
36
36
  }
37
37
  ]
38
38
  },
39
+ "admin.access-rule.bulk-apply": {
40
+ "command": [
41
+ "access-rule",
42
+ "bulk-apply"
43
+ ],
44
+ "examples": [
45
+ {
46
+ "title": "upsert permission matrix by rule name in one transaction",
47
+ "body": {
48
+ "mode": "upsert_by_name",
49
+ "items": [
50
+ {
51
+ "table_id": 2188893443,
52
+ "name": "Customer archive - sales owns rows",
53
+ "enabled": true,
54
+ "type": "form",
55
+ "options": {
56
+ "user_scope": [
57
+ {
58
+ "type": "department",
59
+ "id": 2188881201
60
+ }
61
+ ],
62
+ "policy": {
63
+ "key": "custom",
64
+ "actions": [
65
+ "view",
66
+ "add",
67
+ "edit"
68
+ ],
69
+ "all_fields_read": true,
70
+ "all_fields_write": true,
71
+ "condition": {
72
+ "mode": "and",
73
+ "conditions": [
74
+ {
75
+ "column": "creator",
76
+ "operator": "$eq",
77
+ "value": "[[current_user]]",
78
+ "value_from": 0,
79
+ "value_relation": ""
80
+ }
81
+ ]
82
+ }
83
+ },
84
+ "list_options": {}
85
+ }
86
+ },
87
+ {
88
+ "table_id": 2188893444,
89
+ "name": "Lead review - manager queue",
90
+ "enabled": true,
91
+ "type": "form",
92
+ "options": {
93
+ "user_scope": [
94
+ {
95
+ "type": "actor",
96
+ "id": 2188883301
97
+ }
98
+ ],
99
+ "policy": {
100
+ "key": "custom",
101
+ "actions": [
102
+ "view",
103
+ "edit"
104
+ ],
105
+ "all_fields_read": true,
106
+ "all_fields_write": true,
107
+ "condition": {
108
+ "mode": "and",
109
+ "conditions": [
110
+ {
111
+ "column": ":1004",
112
+ "operator": "$eq",
113
+ "value": "pending",
114
+ "value_from": 0,
115
+ "value_relation": ""
116
+ },
117
+ {
118
+ "column": "",
119
+ "operator": "",
120
+ "value": null,
121
+ "value_from": 0,
122
+ "value_relation": "",
123
+ "subset": {
124
+ "mode": "or",
125
+ "conditions": [
126
+ {
127
+ "column": "creator",
128
+ "operator": "$eq",
129
+ "value": "[[current_user]]",
130
+ "value_from": 0,
131
+ "value_relation": ""
132
+ },
133
+ {
134
+ "column": ":1005",
135
+ "operator": "$eq",
136
+ "value": "high",
137
+ "value_from": 0,
138
+ "value_relation": ""
139
+ }
140
+ ]
141
+ }
142
+ }
143
+ ]
144
+ }
145
+ },
146
+ "list_options": {}
147
+ }
148
+ }
149
+ ]
150
+ },
151
+ "notes": [
152
+ "mode upsert_by_name is for idempotent setup; rule names must be unique within each table",
153
+ "department, actor, and specific user scopes all use options.user_scope",
154
+ "row-owner isolation uses [[current_user]] in policy.condition"
155
+ ]
156
+ },
157
+ {
158
+ "title": "preview updates for existing rule ids",
159
+ "body": {
160
+ "mode": "update_existing",
161
+ "dry_run": true,
162
+ "items": [
163
+ {
164
+ "table_id": 2188893443,
165
+ "rule_id": 2188893557,
166
+ "enabled": true,
167
+ "options": {
168
+ "user_scope": [
169
+ {
170
+ "type": "user",
171
+ "id": 2188889901
172
+ }
173
+ ],
174
+ "policy": {
175
+ "key": "custom",
176
+ "actions": [
177
+ "view"
178
+ ],
179
+ "all_fields_read": true,
180
+ "all_fields_write": false
181
+ },
182
+ "list_options": {}
183
+ }
184
+ }
185
+ ]
186
+ },
187
+ "notes": [
188
+ "dry_run true returns the planned operations without writing",
189
+ "update_existing requires rule_id on every item"
190
+ ]
191
+ }
192
+ ]
193
+ },
39
194
  "admin.access-rule.create": {
40
195
  "command": [
41
196
  "access-rule",
@@ -7,6 +7,10 @@ export declare const typeIndex: {
7
7
  readonly file: "types/app.ts";
8
8
  readonly dependencies: readonly [];
9
9
  };
10
+ readonly AppIngressBulkApplyReqVO: {
11
+ readonly file: "types/ingress.ts";
12
+ readonly dependencies: readonly [];
13
+ };
10
14
  readonly AppIngressCreateReqVO: {
11
15
  readonly file: "types/ingress.ts";
12
16
  readonly dependencies: readonly [];
@@ -1 +1 @@
1
- {"version":3,"file":"type_index.generated.d.ts","sourceRoot":"","sources":["../../src/generated/type_index.generated.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6FZ,CAAA"}
1
+ {"version":3,"file":"type_index.generated.d.ts","sourceRoot":"","sources":["../../src/generated/type_index.generated.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiGZ,CAAA"}
@@ -8,6 +8,10 @@ export const typeIndex = {
8
8
  "file": "types/app.ts",
9
9
  "dependencies": []
10
10
  },
11
+ "AppIngressBulkApplyReqVO": {
12
+ "file": "types/ingress.ts",
13
+ "dependencies": []
14
+ },
11
15
  "AppIngressCreateReqVO": {
12
16
  "file": "types/ingress.ts",
13
17
  "dependencies": []
@@ -15,6 +15,8 @@ export declare const PermitFieldPermitSchema: z.ZodTypeAny;
15
15
  export declare const PermitPolicySchema: z.ZodTypeAny;
16
16
  export declare const PermitUserScopeSchema: z.ZodTypeAny;
17
17
  export declare const EntityIngressOptionsSchema: z.ZodTypeAny;
18
+ export declare const AppIngressBulkApplyItemVOSchema: z.ZodTypeAny;
19
+ export declare const AppIngressBulkApplyReqVOSchema: z.ZodTypeAny;
18
20
  export declare const AppIngressCreateReqVOSchema: z.ZodTypeAny;
19
21
  export declare const AppIngressUpdateReqVOSchema: z.ZodTypeAny;
20
22
  export declare const GormDeletedAtSchema: z.ZodTypeAny;
@@ -79,10 +81,11 @@ export declare const PronounsTypeSchema: z.ZodTypeAny;
79
81
  export declare const UserSchema: z.ZodTypeAny;
80
82
  export declare const TenantUserSchema: z.ZodTypeAny;
81
83
  export declare const UserProfileUpdateReqVOSchema: z.ZodTypeAny;
82
- export declare const generatedRequestTypes: readonly ["AppCreateByTenantsReqVO", "AppCreateEntityReqVO", "AppIngressCreateReqVO", "AppIngressUpdateReqVO", "AppUpdateAppReqVO", "EntityBulkUpdateReqVO", "EntityDoActionReqVO", "EntityQueryRelationReqVO", "EntityQueryReqVO", "EntityResolveWorkflowReqVO", "EntitySaveNameReqVO", "EntitySaveReqVO", "EntitySelectionActionReqVO", "EntityUpdateReqVO", "EntityWorkflowApproveUsersReqVO", "EntityWorkflowDeployReqVO", "EntityWorkflowUpdateReqVO", "GetUploadTokenReqVO", "InsertReqVO", "MobileUploadCheckReqVO", "MobileUploadReqVO", "UploadPreviewReqVO", "UserProfileUpdateReqVO"];
84
+ export declare const generatedRequestTypes: readonly ["AppCreateByTenantsReqVO", "AppCreateEntityReqVO", "AppIngressBulkApplyReqVO", "AppIngressCreateReqVO", "AppIngressUpdateReqVO", "AppUpdateAppReqVO", "EntityBulkUpdateReqVO", "EntityDoActionReqVO", "EntityQueryRelationReqVO", "EntityQueryReqVO", "EntityResolveWorkflowReqVO", "EntitySaveNameReqVO", "EntitySaveReqVO", "EntitySelectionActionReqVO", "EntityUpdateReqVO", "EntityWorkflowApproveUsersReqVO", "EntityWorkflowDeployReqVO", "EntityWorkflowUpdateReqVO", "GetUploadTokenReqVO", "InsertReqVO", "MobileUploadCheckReqVO", "MobileUploadReqVO", "UploadPreviewReqVO", "UserProfileUpdateReqVO"];
83
85
  export declare const bodySchemas: {
84
86
  readonly AppCreateByTenantsReqVO: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
85
87
  readonly AppCreateEntityReqVO: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
88
+ readonly AppIngressBulkApplyReqVO: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
86
89
  readonly AppIngressCreateReqVO: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
87
90
  readonly AppIngressUpdateReqVO: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
88
91
  readonly AppUpdateAppReqVO: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
@@ -1 +1 @@
1
- {"version":3,"file":"zod_registry.generated.d.ts","sourceRoot":"","sources":["../../src/generated/zod_registry.generated.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"zod_registry.generated.d.ts","sourceRoot":"","sources":["../../src/generated/zod_registry.generated.ts"],"names":[],"mappings":"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"}
@@ -16,6 +16,8 @@ export const PermitFieldPermitSchema = z.lazy(() => z.object({ "key": z.string()
16
16
  export const PermitPolicySchema = z.lazy(() => z.object({ "actions": z.array(z.string()).optional(), "all_fields_read": z.boolean().optional(), "all_fields_write": z.boolean().optional(), "condition": PermitConditionSetSchema.optional(), "description": z.string().optional(), "fields": z.array(PermitFieldPermitSchema).optional(), "id": z.string().optional(), "key": z.string().optional(), "name": z.string().optional() }).strict());
17
17
  export const PermitUserScopeSchema = z.lazy(() => z.object({ "data": z.object({ "name": z.string().optional() }).strict().optional(), "id": z.number().optional(), "type": z.string().optional() }).strict());
18
18
  export const EntityIngressOptionsSchema = z.lazy(() => z.object({ "i18n_name": I18NTextSchema.optional(), "list_options": PermitEntityListOptionsSchema.optional(), "policy": PermitPolicySchema.optional(), "user_scope": z.array(PermitUserScopeSchema).optional() }).strict());
19
+ export const AppIngressBulkApplyItemVOSchema = z.lazy(() => z.object({ "enabled": z.boolean().optional(), "name": z.string().optional(), "options": EntityIngressOptionsSchema.optional(), "rule_id": z.number().optional(), "table_id": z.number().optional(), "type": z.string().optional() }).strict());
20
+ export const AppIngressBulkApplyReqVOSchema = z.lazy(() => z.object({ "dry_run": z.boolean().optional(), "items": z.array(AppIngressBulkApplyItemVOSchema).optional(), "mode": z.string().optional() }).strict());
19
21
  export const AppIngressCreateReqVOSchema = z.lazy(() => z.object({ "enabled": z.boolean().optional(), "entity_id": z.number().optional(), "icon_name": z.string().optional(), "name": z.string().optional(), "options": EntityIngressOptionsSchema.optional(), "type": z.string().optional(), "url": z.string().optional() }).strict());
20
22
  export const AppIngressUpdateReqVOSchema = z.lazy(() => z.object({ "enabled": z.boolean().optional(), "name": z.string().optional(), "options": EntityIngressOptionsSchema.optional(), "update": z.array(z.string()).optional() }).strict());
21
23
  export const GormDeletedAtSchema = z.lazy(() => z.object({ "Time": z.string().optional(), "Valid": z.boolean().optional() }).strict());
@@ -83,6 +85,7 @@ export const UserProfileUpdateReqVOSchema = z.lazy(() => z.object({ "Changed": z
83
85
  export const generatedRequestTypes = [
84
86
  "AppCreateByTenantsReqVO",
85
87
  "AppCreateEntityReqVO",
88
+ "AppIngressBulkApplyReqVO",
86
89
  "AppIngressCreateReqVO",
87
90
  "AppIngressUpdateReqVO",
88
91
  "AppUpdateAppReqVO",
@@ -108,6 +111,7 @@ export const generatedRequestTypes = [
108
111
  export const bodySchemas = {
109
112
  "AppCreateByTenantsReqVO": AppCreateByTenantsReqVOSchema,
110
113
  "AppCreateEntityReqVO": AppCreateEntityReqVOSchema,
114
+ "AppIngressBulkApplyReqVO": AppIngressBulkApplyReqVOSchema,
111
115
  "AppIngressCreateReqVO": AppIngressCreateReqVOSchema,
112
116
  "AppIngressUpdateReqVO": AppIngressUpdateReqVOSchema,
113
117
  "AppUpdateAppReqVO": AppUpdateAppReqVOSchema,
@@ -1 +1 @@
1
- {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/runtime/execute.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,UAAU,CAAA;AAG1D,OAAO,EAAyF,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAQhJ,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,YAAY,CAAA;IACnB,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5B,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;CAC9B,CAAA;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAc1D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,MAAM,CAoB7G;AA8BD,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;AAUlD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,MAAM,CA8HpI;AA8xDD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,uBAAuB,CActH;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,SAAS,GAAE,OAAO,KAAa,GAAG,OAAO,CAAC,GAAG,CAAC,CA+NrI"}
1
+ {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/runtime/execute.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,UAAU,CAAA;AAG1D,OAAO,EAAyF,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAQhJ,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,YAAY,CAAA;IACnB,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5B,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;CAC9B,CAAA;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAc1D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,MAAM,CAoB7G;AA8BD,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;AAUlD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,MAAM,CA8HpI;AA04DD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,uBAAuB,CActH;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,SAAS,GAAE,OAAO,KAAa,GAAG,OAAO,CAAC,GAAG,CAAC,CA+NrI"}
@@ -577,6 +577,9 @@ function buildTableCreateExampleBody() {
577
577
  function isAssignUsersCommand(scope, command) {
578
578
  return scope === 'admin' && command.commandPath[0] === 'access-rule' && command.commandPath[1] === 'assign-users';
579
579
  }
580
+ function isAccessRuleBulkApplyCommand(scope, command) {
581
+ return scope === 'admin' && command.commandPath[0] === 'access-rule' && command.commandPath[1] === 'bulk-apply';
582
+ }
580
583
  function isTableCreateCommand(scope, command) {
581
584
  return scope === 'admin' && command.commandPath[0] === 'table' && command.commandPath[1] === 'create';
582
585
  }
@@ -937,31 +940,96 @@ function validateAccessRuleUserScope(scope, command, requestType, userScope, env
937
940
  }
938
941
  }
939
942
  function normalizeNumericAccessRuleUserScopeIDs(scope, command, body) {
940
- if (!isAccessRuleCommand(scope, command) || !isRecord(body) || !isRecord(body.options) || !Array.isArray(body.options.user_scope)) {
943
+ if (!isAccessRuleCommand(scope, command) || !isRecord(body)) {
941
944
  return body;
942
945
  }
943
- let changed = false;
944
- const userScope = body.options.user_scope.map((item) => {
945
- if (!isRecord(item) || typeof item.id !== 'string' || !/^\d+$/.test(item.id)) {
946
- return item;
947
- }
948
- const id = Number(item.id);
949
- if (!Number.isFinite(id) || !Number.isInteger(id)) {
950
- return item;
951
- }
952
- changed = true;
953
- return { ...item, id };
954
- });
955
- if (!changed)
946
+ const normalizeUserScope = (userScope) => {
947
+ if (!Array.isArray(userScope))
948
+ return { value: userScope, changed: false };
949
+ let changed = false;
950
+ const value = userScope.map((item) => {
951
+ if (!isRecord(item) || typeof item.id !== 'string' || !/^\d+$/.test(item.id)) {
952
+ return item;
953
+ }
954
+ const id = Number(item.id);
955
+ if (!Number.isFinite(id) || !Number.isInteger(id)) {
956
+ return item;
957
+ }
958
+ changed = true;
959
+ return { ...item, id };
960
+ });
961
+ return { value, changed };
962
+ };
963
+ const normalizeNumericID = (value) => {
964
+ if (typeof value !== 'string' || !/^\d+$/.test(value))
965
+ return { value, changed: false };
966
+ const id = Number(value);
967
+ if (!Number.isFinite(id) || !Number.isInteger(id))
968
+ return { value, changed: false };
969
+ return { value: id, changed: true };
970
+ };
971
+ if (isAccessRuleBulkApplyCommand(scope, command) && Array.isArray(body.items)) {
972
+ let changed = false;
973
+ const items = body.items.map((item) => {
974
+ if (!isRecord(item))
975
+ return item;
976
+ let nextItem = item;
977
+ for (const key of ['table_id', 'rule_id']) {
978
+ const normalized = normalizeNumericID(nextItem[key]);
979
+ if (normalized.changed) {
980
+ nextItem = { ...nextItem, [key]: normalized.value };
981
+ changed = true;
982
+ }
983
+ }
984
+ if (isRecord(nextItem.options)) {
985
+ const normalizedUserScope = normalizeUserScope(nextItem.options.user_scope);
986
+ if (normalizedUserScope.changed) {
987
+ nextItem = {
988
+ ...nextItem,
989
+ options: {
990
+ ...nextItem.options,
991
+ user_scope: normalizedUserScope.value,
992
+ },
993
+ };
994
+ changed = true;
995
+ }
996
+ }
997
+ return nextItem;
998
+ });
999
+ return changed ? { ...body, items } : body;
1000
+ }
1001
+ if (!isRecord(body.options)) {
1002
+ return body;
1003
+ }
1004
+ const normalizedUserScope = normalizeUserScope(body.options.user_scope);
1005
+ if (!normalizedUserScope.changed)
956
1006
  return body;
957
1007
  return {
958
1008
  ...body,
959
1009
  options: {
960
1010
  ...body.options,
961
- user_scope: userScope,
1011
+ user_scope: normalizedUserScope.value,
962
1012
  },
963
1013
  };
964
1014
  }
1015
+ function validateAccessRulePolicyShape(scope, command, requestType, policy, env, pathPrefix) {
1016
+ const actions = policy && Array.isArray(policy.actions) ? policy.actions : [];
1017
+ if (actions.includes('read') || actions.includes('write')) {
1018
+ throwBodyValidationFailure('access-rule policy.actions must use Arcubase action codes: use "view" for read and "add","edit" for write; do not use "read", "write", or "insert"', requestType, `${pathPrefix}.actions`, scope, command, env);
1019
+ }
1020
+ const fields = policy && Array.isArray(policy.fields) ? policy.fields : [];
1021
+ const allowedSystemFieldKeys = new Set(['created', 'updated', 'creator']);
1022
+ for (const [index, field] of fields.entries()) {
1023
+ if (!isRecord(field))
1024
+ continue;
1025
+ if (typeof field.key === 'number' || (typeof field.key === 'string' && /^\d+$/.test(field.key))) {
1026
+ throwBodyValidationFailure('access-rule policy.fields[].key must be a string prefixed with colon, for example ":1002"; do not use raw numbers', requestType, `${pathPrefix}.fields.${index}.key`, scope, command, env);
1027
+ }
1028
+ if (typeof field.key === 'string' && !field.key.startsWith(':') && !allowedSystemFieldKeys.has(field.key)) {
1029
+ throwBodyValidationFailure('access-rule policy.fields[].key must use Arcubase permission keys such as ":1002"; do not use FieldVO.key values such as "vote_name"', requestType, `${pathPrefix}.fields.${index}.key`, scope, command, env);
1030
+ }
1031
+ }
1032
+ }
965
1033
  function requireUpdateContains(scope, command, body, field, env) {
966
1034
  if (!(field in body))
967
1035
  return;
@@ -987,6 +1055,26 @@ function validateActionSpecificRawBody(scope, command, body, env) {
987
1055
  }
988
1056
  }
989
1057
  if (isAccessRuleCommand(scope, command)) {
1058
+ if (isAccessRuleBulkApplyCommand(scope, command)) {
1059
+ if (!Array.isArray(body.items) || body.items.length === 0) {
1060
+ throwBodyValidationFailure('access-rule bulk-apply requires non-empty body.items; put every table/rule assignment in body.items', command.requestType, 'body.items', scope, command, env);
1061
+ }
1062
+ if (body.mode !== undefined && body.mode !== 'update_existing' && body.mode !== 'upsert_by_name') {
1063
+ throwBodyValidationFailure('access-rule bulk-apply body.mode must be "update_existing" or "upsert_by_name"', command.requestType, 'body.mode', scope, command, env);
1064
+ }
1065
+ for (const [index, item] of body.items.entries()) {
1066
+ if (!isRecord(item)) {
1067
+ throwBodyValidationFailure('access-rule bulk-apply body.items[] must be an object', command.requestType, `body.items.${index}`, scope, command, env);
1068
+ }
1069
+ const options = isRecord(item.options) ? item.options : undefined;
1070
+ if (!options) {
1071
+ throwBodyValidationFailure('access-rule bulk-apply body.items[].options is required and must include the full canonical options object', command.requestType, `body.items.${index}.options`, scope, command, env);
1072
+ }
1073
+ validateAccessRuleUserScope(scope, command, command.requestType, options.user_scope, env, `body.items.${index}.options.user_scope`);
1074
+ validateAccessRulePolicyShape(scope, command, command.requestType, isRecord(options.policy) ? options.policy : undefined, env, `body.items.${index}.options.policy`);
1075
+ }
1076
+ return;
1077
+ }
990
1078
  const update = stringArray(body.update);
991
1079
  if (isAccessRuleUpdateCommand(scope, command) && update.some((item) => item.startsWith('options.'))) {
992
1080
  throwBodyValidationFailure('access-rule update cannot patch nested options paths. Use {"update":["options"],"options":{"policy":{"key":"custom","actions":["view","add","edit"],"all_fields_read":true,"all_fields_write":true,"fields":[{"key":":1002","read":false,"write":false,"report":false}]},"list_options":{}}}', command.requestType, 'body.update', scope, command, env);
@@ -1003,22 +1091,7 @@ function validateActionSpecificRawBody(scope, command, body, env) {
1003
1091
  throwBodyValidationFailure('access-rule update with update:["options"] cannot change only options.user_scope because it overwrites policy. Use access-rule assign-users for user assignment, or include the full options.policy and options.list_options.', command.requestType, 'body.options.policy', scope, command, env);
1004
1092
  }
1005
1093
  validateAccessRuleUserScope(scope, command, command.requestType, options?.user_scope, env);
1006
- const actions = policy && Array.isArray(policy.actions) ? policy.actions : [];
1007
- if (actions.includes('read') || actions.includes('write')) {
1008
- throwBodyValidationFailure('access-rule policy.actions must use Arcubase action codes: use "view" for read and "add","edit" for write; do not use "read", "write", or "insert"', command.requestType, 'body.options.policy.actions', scope, command, env);
1009
- }
1010
- const fields = policy && Array.isArray(policy.fields) ? policy.fields : [];
1011
- const allowedSystemFieldKeys = new Set(['created', 'updated', 'creator']);
1012
- for (const [index, field] of fields.entries()) {
1013
- if (!isRecord(field))
1014
- continue;
1015
- if (typeof field.key === 'number' || (typeof field.key === 'string' && /^\d+$/.test(field.key))) {
1016
- throwBodyValidationFailure('access-rule policy.fields[].key must be a string prefixed with colon, for example ":1002"; do not use raw numbers', command.requestType, `body.options.policy.fields.${index}.key`, scope, command, env);
1017
- }
1018
- if (typeof field.key === 'string' && !field.key.startsWith(':') && !allowedSystemFieldKeys.has(field.key)) {
1019
- throwBodyValidationFailure('access-rule policy.fields[].key must use Arcubase permission keys such as ":1002"; do not use FieldVO.key values such as "vote_name"', command.requestType, `body.options.policy.fields.${index}.key`, scope, command, env);
1020
- }
1021
- }
1094
+ validateAccessRulePolicyShape(scope, command, command.requestType, policy, env, 'body.options.policy');
1022
1095
  }
1023
1096
  }
1024
1097
  function validateActionSpecificBody(scope, command, flags, body, env) {
@@ -1 +1 @@
1
- {"version":3,"file":"zod_registry.d.ts","sourceRoot":"","sources":["../../src/runtime/zod_registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AA8BrC,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAOjE;AAED,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI9E;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAQ9D;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;AAyGlD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,eAAe,EAAE,CAqB7F;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,cAAc,EAAE,CAI3F;AAwED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,cAAc,EAAE,CAInG"}
1
+ {"version":3,"file":"zod_registry.d.ts","sourceRoot":"","sources":["../../src/runtime/zod_registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AA8BrC,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAOjE;AAED,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI9E;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAQ9D;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;AA6GlD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,eAAe,EAAE,CAqB7F;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,cAAc,EAAE,CAI3F;AA4ED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,cAAc,EAAE,CAInG"}
@@ -79,6 +79,10 @@ const docHintIndex = {
79
79
  { title: 'Access rule', file: 'docs/runtime-reference/access-rule.md' },
80
80
  examplesIndexDocHint,
81
81
  ],
82
+ AppIngressBulkApplyReqVO: [
83
+ { title: 'Access rule', file: 'docs/runtime-reference/access-rule.md' },
84
+ examplesIndexDocHint,
85
+ ],
82
86
  EntitySaveReqVO: [
83
87
  { title: 'Table schema cheatsheet', file: 'docs/runtime-reference/entity-schema.md' },
84
88
  { title: 'Field type index', file: 'docs/runtime-reference/entity-schema/README.md' },
@@ -197,6 +201,10 @@ const commandDocHintIndex = {
197
201
  { title: 'Access rule', file: 'docs/runtime-reference/access-rule.md' },
198
202
  examplesIndexDocHint,
199
203
  ],
204
+ 'admin.access-rule.bulkApplyEntityIngress': [
205
+ { title: 'Access rule', file: 'docs/runtime-reference/access-rule.md' },
206
+ examplesIndexDocHint,
207
+ ],
200
208
  'user.row.insertEntity': [
201
209
  { title: 'Row CRUD', file: 'docs/runtime-reference/row-crud.md' },
202
210
  { title: 'Uploads', file: 'docs/runtime-reference/uploads.md' },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@carthooks/arcubase-cli",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "Arcubase runtime CLI for admin and user command execution",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -7,6 +7,8 @@ import type {
7
7
  AppIngressGetBlocksRespVO,
8
8
  AppIngressGetByHashIDRespVO,
9
9
  AppIngressListRespVO,
10
+ AppIngressBulkApplyReqVO,
11
+ AppIngressBulkApplyRespVO,
10
12
  AppIngressUpdateReqVO,
11
13
  AppIngressUpdateRespVO,
12
14
  AppIngressUpdateBlocksReqVO,
@@ -83,6 +85,15 @@ export async function getEntityIngressList(
83
85
  return getDefaultClient().get(`/apps/${appId}/entity/${entityId}/ingress`)
84
86
  }
85
87
 
88
+ // @endpoint POST /apps/:app_id/access-rules/bulk-apply
89
+ // @controller App.IngressBulkApply
90
+ export async function bulkApplyEntityIngress(
91
+ appId: string,
92
+ data: AppIngressBulkApplyReqVO
93
+ ): Promise<AppIngressBulkApplyRespVO> {
94
+ return getDefaultClient().post(`/apps/${appId}/access-rules/bulk-apply`, data)
95
+ }
96
+
86
97
  // @endpoint PUT /apps/:app_id/entity/:entity_id/ingress/:id
87
98
  // @controller App.IngressUpdate
88
99
  export async function updateEntityIngress(
@@ -112,6 +112,25 @@ Rules:
112
112
  - Multiple scope items are OR: any matching user, department membership, or actor membership can use the ingress.
113
113
  - Department scope includes child departments because Arcubase matches the user's department path.
114
114
 
115
+ ## Bulk Apply Across Tables
116
+
117
+ Use this when assigning or updating many access rules for one app. This is the single path for matrix-style permission setup. Do not loop `access-rule list` and `access-rule update` for every table/rule.
118
+
119
+ ```bash
120
+ arcubase-admin access-rule bulk-apply \
121
+ --app-id 2188893436 \
122
+ --body-json '{"mode":"upsert_by_name","items":[{"table_id":2188893443,"name":"Sales read write","enabled":true,"type":"form","options":{"user_scope":[{"type":"department","id":2188881201}],"policy":{"key":"custom","actions":["view","add","edit"],"all_fields_read":true,"all_fields_write":true,"condition":{"mode":"and","conditions":[{"column":"creator","operator":"$eq","value":"[[current_user]]","value_from":0,"value_relation":""}]}},"list_options":{}}},{"table_id":2188893444,"name":"Sales readonly","enabled":true,"type":"form","options":{"user_scope":[{"type":"actor","id":2188883301}],"policy":{"key":"custom","actions":["view"],"all_fields_read":true,"all_fields_write":false},"list_options":{}}}]}'
123
+ ```
124
+
125
+ Rules:
126
+
127
+ - `bulk-apply` runs in one backend transaction.
128
+ - `mode:"update_existing"` requires every item to include `rule_id`.
129
+ - `mode:"upsert_by_name"` requires every item to include `name` and must not include `rule_id`.
130
+ - Each item must include `table_id` and the full canonical `options` object.
131
+ - Numeric IDs passed as strings are normalized by the CLI for `table_id`, `rule_id`, and `options.user_scope[].id`.
132
+ - Use `dry_run:true` to preview the exact operations without writing.
133
+
115
134
  ## Verify
116
135
 
117
136
  ```bash