@arcforgelabs/flow 2026.10.24 → 2026.10.25

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Flow
2
2
 
3
- Flow is invoicing, bill approval and a financial dashboard for labs that make
3
+ Flow is job management, invoicing, bill approval and a financial dashboard for labs that make
4
4
  work to order, first for dental labs. Seazona (the lab's case system) is a
5
5
  bundled integration, and Xero is an optional one. See `VISION.md`.
6
6
 
package/VISION.md CHANGED
@@ -1,21 +1,24 @@
1
1
  # Flow — Vision
2
2
 
3
- Flow is invoicing, bill approval and a financial dashboard for a lab that
4
- makes work to order, first for dental labs. It is a complete application with
5
- its own database. It is not a sync engine between other products.
6
-
7
- It is for the person who bills the work and pays the suppliers. Finished feels
8
- like this: completed cases become invoices they check and send, supplier bills
9
- are reviewed and approved, and one dashboard shows cash, what is owed to the
10
- lab, what the lab owes, and the GST for the BAS period. Every invoice a
11
- customer was sent can be found again, exactly as it was sent.
3
+ Flow is job management, invoicing, bill approval and a financial dashboard
4
+ for a lab that makes work to order, first for dental labs. It is a complete
5
+ application with its own database. It is not a sync engine between other
6
+ products.
7
+
8
+ It is for the lab manager, the staff who move the work, and the person who
9
+ bills it and pays the suppliers. Finished feels like this: Flow opens on a
10
+ job board that shows every job by stage, with due dates and late jobs marked;
11
+ completed jobs become invoices they check and send; supplier bills are
12
+ reviewed and approved; and one dashboard shows cash, what is owed to the lab,
13
+ what the lab owes, and the GST for the BAS period. Every invoice a customer
14
+ was sent can be found again, exactly as it was sent.
12
15
 
13
16
  Flow is open source so any lab can run its own installation.
14
17
 
15
18
  ## The core and its integrations
16
19
 
17
- The core is invoices, bills, payments, credit notes, contacts, the price list,
18
- the jobs it bills, approvals and the dashboard. The core holds its own copy of
20
+ The core is jobs and the job board, invoices, bills, payments, credit notes,
21
+ contacts, the price list, approvals and the dashboard. The core holds its own copy of
19
22
  every record it shows, so it works with no integration connected and an owner
20
23
  can build reports and features on its data.
21
24
 
@@ -33,6 +36,39 @@ data spine (`docs/DATA_SPINE.md`): its records come into a mirror, get a Flow
33
36
  identity, and become core records; Flow's writes leave through an outbox; a
34
37
  conflict goes to one review queue; one job queue runs the work.
35
38
 
39
+ ## Job management
40
+
41
+ Flow links each job to its client and its invoice. That link is the heart
42
+ of the product: a job card shows what was ordered, who it is for, and how it
43
+ was billed and paid.
44
+
45
+ Flow does a few parts of job management well now, and more later. It does
46
+ not try to replace the lab's case system.
47
+
48
+ - **Now:** update job cards and process a job's information for invoicing,
49
+ and update jobs from paper forms.
50
+ - **Later:** full job management.
51
+
52
+ The job board is Flow's main view: a standard board of jobs by stage (a
53
+ column per stage, a card per job), with a list view of the same jobs. It
54
+ shows every job from the case system and from Flow, with its practice, due
55
+ date and department. Lab staff and the manager work from it.
56
+
57
+ Two parts follow the board (#48):
58
+
59
+ - **An intake reader.** A photo, a form or a note becomes a proposed job
60
+ action: update a job, create one, or add a note. A handwriting reader and a
61
+ low-cost decision model propose it; a person confirms it. Nothing changes
62
+ until a person accepts. The model steps are optional and cost money per
63
+ page, so the manager sees the month's cost.
64
+ - **A practice portal.** Practice staff sign in to follow their own jobs,
65
+ on desktop first, with a simpler view on phones. The server limits each
66
+ person to their practice.
67
+
68
+ Job management is a bundled module, built the same way as the integrations,
69
+ and a lab can remove it. Where the case system cannot take a change through
70
+ its API, the change becomes a short checklist for a person (#49).
71
+
36
72
  ## Standing decisions
37
73
 
38
74
  ### Why does Flow keep its own records?
@@ -58,7 +94,10 @@ not the product.
58
94
  The case system, Flow and the accounting system each own their own records,
59
95
  and the data moves both ways. Flow records which system each change came
60
96
  from. When two systems disagree, Flow never overwrites one silently: it opens
61
- an item in the review queue for a person.
97
+ an alert in the review queue. The alert shows each system's value and writes
98
+ nothing. A person fixes the record where they choose, then presses
99
+ **Resolved, re-check**: Flow checks that one difference again, and the alert
100
+ closes only when the systems agree.
62
101
 
63
102
  ### Why are approvals in Flow?
64
103
 
@@ -76,7 +115,8 @@ version; the sent one stays as it was, attributed to whoever sent it.
76
115
  Dental cases carry health information, which Australian privacy law treats as
77
116
  sensitive. Flow keeps the case number and the practice. It keeps a patient
78
117
  reference only when a practice needs one printed on its invoice, and it keeps
79
- no clinical notes or images.
118
+ no clinical notes or images. A form photo the intake reader reads is not kept
119
+ after its job is updated.
80
120
 
81
121
  ### Why does Flow keep its records in PostgreSQL only?
82
122
 
@@ -94,8 +134,9 @@ its own data, configuration and secrets.
94
134
 
95
135
  ## Out of scope
96
136
 
97
- - Case management, production tracking and scheduling. The case system owns
98
- the case.
137
+ - Replacing the case system, for now. The case system owns the case record.
138
+ Flow's job board shows and updates the work, and does not do clinical
139
+ case management or production scheduling.
99
140
  - Patient records, clinical notes, scans and images.
100
141
  - Acting as the general ledger. Accounting software owns the ledger and the
101
142
  bank feed.
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@arcforgelabs/flow",
3
- "version": "2026.10.24",
3
+ "version": "2026.10.25",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@arcforgelabs/flow",
9
- "version": "2026.10.24",
9
+ "version": "2026.10.25",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@clerk/backend": "3.23.2",
@@ -19,6 +19,7 @@
19
19
  "@fontsource-variable/lora": "5.3.0",
20
20
  "@fontsource-variable/nunito-sans": "5.3.0",
21
21
  "@fontsource-variable/playfair-display": "5.3.0",
22
+ "@fontsource-variable/plus-jakarta-sans": "5.3.0",
22
23
  "@fontsource-variable/space-grotesk": "5.3.0",
23
24
  "drizzle-orm": "0.45.3",
24
25
  "express": "5.3.0",
@@ -630,6 +631,15 @@
630
631
  "url": "https://github.com/sponsors/ayuhito"
631
632
  }
632
633
  },
634
+ "node_modules/@fontsource-variable/plus-jakarta-sans": {
635
+ "version": "5.3.0",
636
+ "resolved": "https://registry.npmjs.org/@fontsource-variable/plus-jakarta-sans/-/plus-jakarta-sans-5.3.0.tgz",
637
+ "integrity": "sha512-/l/4r0yyWK9JzAlmA0LiYgGgmJe/Gswt4jTJEzr5QhJfwMbvJZDmYWyW0M4X7yCK69BajMVlV/Lx8g7WDc1+sw==",
638
+ "license": "OFL-1.1",
639
+ "funding": {
640
+ "url": "https://github.com/sponsors/ayuhito"
641
+ }
642
+ },
633
643
  "node_modules/@fontsource-variable/space-grotesk": {
634
644
  "version": "5.3.0",
635
645
  "resolved": "https://registry.npmjs.org/@fontsource-variable/space-grotesk/-/space-grotesk-5.3.0.tgz",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcforgelabs/flow",
3
- "version": "2026.10.24",
3
+ "version": "2026.10.25",
4
4
  "description": "Invoicing, bill entry and a financial dashboard for labs, with Seazona and Xero integrations.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -44,6 +44,7 @@
44
44
  "@fontsource-variable/lora": "5.3.0",
45
45
  "@fontsource-variable/nunito-sans": "5.3.0",
46
46
  "@fontsource-variable/playfair-display": "5.3.0",
47
+ "@fontsource-variable/plus-jakarta-sans": "5.3.0",
47
48
  "@fontsource-variable/space-grotesk": "5.3.0",
48
49
  "drizzle-orm": "0.45.3",
49
50
  "express": "5.3.0",
@@ -6,6 +6,7 @@ export const MONO_FONT = 'jetbrains-mono';
6
6
 
7
7
  export const FAMILY_FONTS = {
8
8
  harbour: ['nunito-sans', 'playfair-display'],
9
+ meridian: ['plus-jakarta-sans', 'playfair-display'],
9
10
  beacon: ['atkinson-hyperlegible-next'],
10
11
  tide: ['ibm-plex-sans'],
11
12
  claw: ['instrument-sans'],
@@ -66,10 +66,64 @@ const HARBOUR = {
66
66
  },
67
67
  };
68
68
 
69
- // Picker order: Harbour (Flow's own), then the design directions Field leads
70
- // with (Beacon, Tide, Claw, Knot, Dash), then the other OpenClaw families.
69
+ // Meridian: a dental laboratory's own look. Deep navy ink and filled buttons,
70
+ // a champagne highlight, warm stone pages and white cards. Plus Jakarta Sans
71
+ // for reading, Playfair Display at regular weight for page titles, square
72
+ // corners and widely tracked uppercase labels. Dark mode turns the navy into
73
+ // the page and the champagne into the accent.
74
+ const MERIDIAN_SHAPE = {
75
+ '--t-body': "'Plus Jakarta Sans Variable', 'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', sans-serif",
76
+ '--t-display': "'Playfair Display Variable', 'Playfair Display', Georgia, 'Times New Roman', serif",
77
+ '--t-data': "'JetBrains Mono Variable', 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace",
78
+ '--t-radius': '0px',
79
+ '--t-radius-lg': '2px',
80
+ '--t-stroke': '1px',
81
+ '--t-label-size': '12px',
82
+ '--t-label-weight': '600',
83
+ '--t-label-spacing': '.16em',
84
+ '--t-label-case': 'uppercase',
85
+ '--t-display-weight': '400',
86
+ };
87
+
88
+ const MERIDIAN = {
89
+ label: 'Meridian',
90
+ description: 'Navy, champagne & stone',
91
+ source: 'flow',
92
+ light: {
93
+ '--t-bg': '#f6f3ef', '--t-s1': '#efe9e0', '--t-s2': '#e6ded1', '--t-paper': '#ffffff',
94
+ '--t-brd': '#e0dbd1', '--t-brd-hi': '#b8a685', '--t-stroke-color': '#d5cec2',
95
+ '--t-text': '#1d3444', '--t-strong': '#13242f', '--t-dim': '#4d6575', '--t-mute': '#526a7a',
96
+ '--t-accent': '#1d3444', '--t-accent-bg': '#faefdd', '--t-accent-brd': '#d4b07a',
97
+ '--t-brand': '#1d3444', '--t-brand-ink': '#f8dfb9',
98
+ '--t-primary': '#1d3444', '--t-on-primary': '#f8dfb9', '--t-ring': '#b08850',
99
+ '--t-warn': '#8a5a00', '--t-warn-bg': 'rgba(138, 90, 0, 0.08)', '--t-warn-brd': 'rgba(138, 90, 0, 0.32)',
100
+ '--t-danger': '#b42318', '--t-danger-bg': 'rgba(180, 35, 24, 0.07)', '--t-danger-brd': 'rgba(180, 35, 24, 0.40)',
101
+ '--t-success': '#22663f', '--t-success-bg': 'rgba(34, 102, 63, 0.08)',
102
+ ...MERIDIAN_SHAPE,
103
+ '--t-shadow': '0 1px 2px rgba(29, 52, 68, 0.06)',
104
+ 'color-scheme': 'light',
105
+ },
106
+ dark: {
107
+ '--t-bg': '#14252f', '--t-s1': '#1d3444', '--t-s2': '#26404f', '--t-paper': '#192d3a',
108
+ '--t-brd': '#2c4555', '--t-brd-hi': '#56707f', '--t-stroke-color': '#334d5e',
109
+ '--t-text': '#ece5d8', '--t-strong': '#fbf4e8', '--t-dim': '#b9c3c9', '--t-mute': '#a3b2bb',
110
+ '--t-accent': '#f8dfb9', '--t-accent-bg': 'rgba(248, 223, 185, 0.12)', '--t-accent-brd': 'rgba(248, 223, 185, 0.45)',
111
+ '--t-brand': '#f8dfb9', '--t-brand-ink': '#1d3444',
112
+ '--t-primary': '#f8dfb9', '--t-on-primary': '#1d3444', '--t-ring': '#f8dfb9',
113
+ '--t-warn': '#e7b75c', '--t-warn-bg': 'rgba(231, 183, 92, 0.12)', '--t-warn-brd': 'rgba(231, 183, 92, 0.32)',
114
+ '--t-danger': '#f2877b', '--t-danger-bg': 'rgba(242, 135, 123, 0.12)', '--t-danger-brd': 'rgba(242, 135, 123, 0.45)',
115
+ '--t-success': '#86d3a1', '--t-success-bg': 'rgba(134, 211, 161, 0.12)',
116
+ ...MERIDIAN_SHAPE,
117
+ '--t-shadow': '0 1px 2px rgba(0, 0, 0, 0.30)',
118
+ 'color-scheme': 'dark',
119
+ },
120
+ };
121
+
122
+ // Picker order: Flow's own (Harbour, Meridian), then the design directions
123
+ // Field leads with (Beacon, Tide, Claw, Knot, Dash), then the other OpenClaw
124
+ // families.
71
125
  const { beacon, tide, claw, knot, dash, ...otherOpenclaw } = OPENCLAW_FAMILIES;
72
- const FAMILIES = { harbour: HARBOUR, beacon, tide, claw, knot, dash, ...otherOpenclaw };
126
+ const FAMILIES = { harbour: HARBOUR, meridian: MERIDIAN, beacon, tide, claw, knot, dash, ...otherOpenclaw };
73
127
 
74
128
  // --t-control: the edge of an input or an outlined button on --t-paper, the
75
129
  // text colour faded toward the paper only as far as it still reads at 3:1.