@lotics/cli 0.317.1 → 0.318.2
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/src/cli.js +6 -6
- package/docs/agent_surface.md +1 -1
- package/docs/building_an_app.md +25 -1
- package/docs/examples.md +33 -0
- package/docs/first_build.md +1 -1
- package/package.json +1 -1
package/docs/agent_surface.md
CHANGED
|
@@ -281,7 +281,7 @@ Acts: every figure or list whose definition is the business's own (open orders,
|
|
|
281
281
|
}
|
|
282
282
|
```
|
|
283
283
|
|
|
284
|
-
It reads under the
|
|
284
|
+
It reads under the app's `rows` (every row, where the app states none of the table) and, on the app's own table, exactly the rows its list reads —
|
|
285
285
|
so never the table of an app that states Books, whose list reads several tables. A condition reading an
|
|
286
286
|
optional param narrows nothing when the call leaves it out; no param compares a number read in each row's
|
|
287
287
|
own unit or currency, or a date holding a span. `"reading"` in place of `"fields"` returns a count or a sum —
|
package/docs/building_an_app.md
CHANGED
|
@@ -93,7 +93,8 @@ nothing; a refusal lists everything wrong in it at once.
|
|
|
93
93
|
|
|
94
94
|
The App node is the app: its `name`, `description`, `icon` and `color` are props of it, and no other input of
|
|
95
95
|
`set_app` states them. It names the tables and templates it uses by their aliases (an entity is a table's alias, a `template` a template's alias);
|
|
96
|
-
`set_app` fills the `tables` and `templates` maps by id from them and `get_app` shows aliases (`lotics docs reference/app-node`).
|
|
96
|
+
`set_app` fills the `tables` and `templates` maps by id from them and `get_app` shows aliases (`lotics docs reference/app-node`).
|
|
97
|
+
Who reads which rows is the app's `rows` (§ Who reads which rows, below). A call that creates
|
|
97
98
|
is `{"body": <the App tree>}`; one that changes a part is `{"app_id": "app_…", "nodes": {"<address>": <patch>}}`,
|
|
98
99
|
each address a node's path of keys (`get_app` prints every one), a patch a JSON merge patch of that node's props
|
|
99
100
|
and `null` removing the node; the App's own props change through `body`. A call stating `base_version_id` — the
|
|
@@ -135,6 +136,29 @@ family and how it is called. A question the screen never asks is a Query node th
|
|
|
135
136
|
(`lotics docs reference/query-node`), beside its Workflow nodes. Both are part of the design: `lotics docs
|
|
136
137
|
agent_surface`, § Declaring more.
|
|
137
138
|
|
|
139
|
+
### Who reads which rows
|
|
140
|
+
|
|
141
|
+
An app runs with its owner's access, and the people it is shared with need the app alone, never its tables. Who of them
|
|
142
|
+
reads which rows is the app's `rows`, one rule per table in the grammar of a table's `read_scope` (`lotics docs reference/read-scope`); it narrows
|
|
143
|
+
the app's screens, its queries and workflows called through it (`run_app_query`, `run_app_workflow`), its acts and its
|
|
144
|
+
workflow bodies alike, and a record id a caller passes is refused where the rule hides the row. State a rule only where
|
|
145
|
+
people differ; a table with none is read whole by everyone the app is shared with.
|
|
146
|
+
|
|
147
|
+
| The business says | The app states |
|
|
148
|
+
|---|---|
|
|
149
|
+
| Everyone on the team sees every order | nothing |
|
|
150
|
+
| Each rep sees only their own deals | `"rows": { "deal": { "any": [{ "field": "rep", "is": "self" }] } }` |
|
|
151
|
+
| Reps see their own deals; managers see all | `"rows": { "deal": { "any": [{ "field": "rep", "is": "self" }, { "member_of": "<managers group id>" }] } }` |
|
|
152
|
+
| Each branch manager sees their branch's orders | `"rows": { "order": { "any": [{ "through": ["branch"], "field": "manager", "is": "self" }] } }` |
|
|
153
|
+
| Each employee sees only their own payslips; HR sees all | two apps: one stating `"payslip": { "any": [{ "field": "employee", "is": "self" }] }`, one for HR stating none |
|
|
154
|
+
| Team leads see people, not salaries | an app that draws no salary field — what it does not show, no one reads through it |
|
|
155
|
+
|
|
156
|
+
A child read under a ruled row states its own rule, through its link to the parent; only a status history inherits.
|
|
157
|
+
Admins are not narrowed in an app; someone on a public link, signed in as no one, reads no row a `self` clause would
|
|
158
|
+
choose. An app never reads past its owner's own access. A table's own `read_scope` governs opening the table directly.
|
|
159
|
+
Working inside one row of a folder (`scope`) narrows the view, not who may read: a branch app shared with every manager
|
|
160
|
+
still states the branch rule.
|
|
161
|
+
|
|
138
162
|
## 5 — A custom-code app
|
|
139
163
|
|
|
140
164
|
```
|
package/docs/examples.md
CHANGED
|
@@ -75,6 +75,14 @@ among them: the `design` reference. Every key: the `model` reference, at the pag
|
|
|
75
75
|
"name": "Service visits",
|
|
76
76
|
"icon": "calendar",
|
|
77
77
|
"color": "emerald",
|
|
78
|
+
"rows": {
|
|
79
|
+
"customer": {"any": [{"member_of": "sales"}]},
|
|
80
|
+
"order": {"any": [{"member_of": "sales"}, {"member_of": "stores"}]},
|
|
81
|
+
"order_line": {"any": [{"member_of": "sales"}, {"member_of": "stores"}]},
|
|
82
|
+
"payment": {"any": [{"member_of": "sales"}, {"member_of": "stores"}]},
|
|
83
|
+
"order_stage": {"any": [{"member_of": "sales"}, {"member_of": "stores"}]},
|
|
84
|
+
"service_visit": {"any": [{"member_of": "sales"}, {"member_of": "stores"}, {"member_of": "field"}]}
|
|
85
|
+
},
|
|
78
86
|
"children": [
|
|
79
87
|
{
|
|
80
88
|
"type": "List",
|
|
@@ -258,6 +266,14 @@ among them: the `design` reference. Every key: the `model` reference, at the pag
|
|
|
258
266
|
"name": "Dispatch",
|
|
259
267
|
"icon": "wrench",
|
|
260
268
|
"color": "sky",
|
|
269
|
+
"rows": {
|
|
270
|
+
"customer": {"any": [{"member_of": "sales"}]},
|
|
271
|
+
"order": {"any": [{"member_of": "sales"}, {"member_of": "stores"}]},
|
|
272
|
+
"order_line": {"any": [{"member_of": "sales"}, {"member_of": "stores"}]},
|
|
273
|
+
"payment": {"any": [{"member_of": "sales"}, {"member_of": "stores"}]},
|
|
274
|
+
"order_stage": {"any": [{"member_of": "sales"}, {"member_of": "stores"}]},
|
|
275
|
+
"service_visit": {"any": [{"member_of": "sales"}, {"member_of": "stores"}, {"member_of": "field"}]}
|
|
276
|
+
},
|
|
261
277
|
"children": [
|
|
262
278
|
{
|
|
263
279
|
"type": "List",
|
|
@@ -613,6 +629,13 @@ among them: the `design` reference. Every key: the `model` reference, at the pag
|
|
|
613
629
|
"name": "Stock",
|
|
614
630
|
"icon": "boxes",
|
|
615
631
|
"color": "teal",
|
|
632
|
+
"rows": {
|
|
633
|
+
"customer": {"any": [{"member_of": "sales"}]},
|
|
634
|
+
"order": {"any": [{"member_of": "sales"}, {"member_of": "stores"}]},
|
|
635
|
+
"order_line": {"any": [{"member_of": "sales"}, {"member_of": "stores"}]},
|
|
636
|
+
"payment": {"any": [{"member_of": "sales"}, {"member_of": "stores"}]},
|
|
637
|
+
"order_stage": {"any": [{"member_of": "sales"}, {"member_of": "stores"}]}
|
|
638
|
+
},
|
|
616
639
|
"scope": "warehouse",
|
|
617
640
|
"children": [
|
|
618
641
|
{
|
|
@@ -841,6 +864,16 @@ among them: the `design` reference. Every key: the `model` reference, at the pag
|
|
|
841
864
|
"name": "Customers",
|
|
842
865
|
"icon": "users",
|
|
843
866
|
"color": "violet",
|
|
867
|
+
"rows": {
|
|
868
|
+
"customer": {"any": [{"member_of": "sales"}]},
|
|
869
|
+
"order": {"any": [{"member_of": "sales"}, {"member_of": "stores"}]},
|
|
870
|
+
"order_line": {"any": [{"member_of": "sales"}, {"member_of": "stores"}]},
|
|
871
|
+
"payment": {"any": [{"member_of": "sales"}, {"member_of": "stores"}]},
|
|
872
|
+
"order_stage": {"any": [{"member_of": "sales"}, {"member_of": "stores"}]},
|
|
873
|
+
"touch": {"any": [{"member_of": "sales"}]},
|
|
874
|
+
"customer_paper": {"any": [{"member_of": "sales"}]},
|
|
875
|
+
"service_visit": {"any": [{"member_of": "sales"}, {"member_of": "stores"}, {"member_of": "field"}]}
|
|
876
|
+
},
|
|
844
877
|
"children": [
|
|
845
878
|
{
|
|
846
879
|
"type": "List",
|
package/docs/first_build.md
CHANGED
|
@@ -142,7 +142,7 @@ One app, the counter's job, over the tables and template above. The register lis
|
|
|
142
142
|
- `app.names-declared`: each alias a key names exists (a table, field, option, Act `key`, template).
|
|
143
143
|
- A workflow writes a link as ids, `[x.id]`; a whole record or bare value is refused.
|
|
144
144
|
|
|
145
|
-
Then `set_access` gives the app to the people whose job it is: a `principal_type` of `member` (id from `get_workspace`, `kind: "member"`), `member_group` (an admin lists them: `kind: "group"`) or `organization`, a `role` of `user` or `manager`; none loses access.
|
|
145
|
+
Then `set_access` gives the app to the people whose job it is: a `principal_type` of `member` (id from `get_workspace`, `kind: "member"`), `member_group` (an admin lists them: `kind: "group"`) or `organization`, a `role` of `user` or `manager`; none loses access. They need no table access; with no `rows` on the App, they read every row.
|
|
146
146
|
|
|
147
147
|
```
|
|
148
148
|
set_access {"resources": [{"resource_type": "app", "resource_id": "app_…"}], "principals": [{"principal_type": "member", "principal_id": "<member id>", "role": "user"}]}
|