@basementuniverse/kanbn 1.1.0 → 2.0.0

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 (124) hide show
  1. package/README.md +2 -0
  2. package/coverage/base.css +224 -0
  3. package/coverage/block-navigation.js +87 -0
  4. package/coverage/coverage-summary.json +31 -0
  5. package/coverage/favicon.png +0 -0
  6. package/coverage/index.html +146 -0
  7. package/coverage/kanbn/index.html +116 -0
  8. package/coverage/kanbn/index.js.html +217 -0
  9. package/coverage/kanbn/src/board.js.html +646 -0
  10. package/coverage/kanbn/src/controller/add.js.html +1729 -0
  11. package/coverage/kanbn/src/controller/archive.js.html +277 -0
  12. package/coverage/kanbn/src/controller/board.js.html +217 -0
  13. package/coverage/kanbn/src/controller/burndown.js.html +607 -0
  14. package/coverage/kanbn/src/controller/comment.js.html +397 -0
  15. package/coverage/kanbn/src/controller/edit.js.html +2920 -0
  16. package/coverage/kanbn/src/controller/find.js.html +1597 -0
  17. package/coverage/kanbn/src/controller/gantt.js.html +1342 -0
  18. package/coverage/kanbn/src/controller/help.js.html +115 -0
  19. package/coverage/kanbn/src/controller/history.js.html +400 -0
  20. package/coverage/kanbn/src/controller/index.html +431 -0
  21. package/coverage/kanbn/src/controller/init.js.html +511 -0
  22. package/coverage/kanbn/src/controller/move.js.html +514 -0
  23. package/coverage/kanbn/src/controller/remove-all.js.html +226 -0
  24. package/coverage/kanbn/src/controller/remove.js.html +307 -0
  25. package/coverage/kanbn/src/controller/rename.js.html +397 -0
  26. package/coverage/kanbn/src/controller/restore.js.html +268 -0
  27. package/coverage/kanbn/src/controller/sort.js.html +1318 -0
  28. package/coverage/kanbn/src/controller/sprint.js.html +361 -0
  29. package/coverage/kanbn/src/controller/status.js.html +310 -0
  30. package/coverage/kanbn/src/controller/task.js.html +244 -0
  31. package/coverage/kanbn/src/controller/validate.js.html +367 -0
  32. package/coverage/kanbn/src/controller/version.js.html +100 -0
  33. package/coverage/kanbn/src/index.html +191 -0
  34. package/coverage/kanbn/src/main.js.html +9787 -0
  35. package/coverage/kanbn/src/parse-index.js.html +1063 -0
  36. package/coverage/kanbn/src/parse-markdown.js.html +202 -0
  37. package/coverage/kanbn/src/parse-task.js.html +2191 -0
  38. package/coverage/kanbn/src/utility.js.html +616 -0
  39. package/coverage/lcov.info +11837 -0
  40. package/coverage/prettify.css +1 -0
  41. package/coverage/prettify.js +2 -0
  42. package/coverage/sort-arrow-sprite.png +0 -0
  43. package/coverage/sorter.js +210 -0
  44. package/coverage/tmp/coverage-214292-1787777191526-0.json +1 -0
  45. package/coverage/tmp/coverage-214293-1787777184569-0.json +1 -0
  46. package/docs/advanced-configuration.md +2 -0
  47. package/docs/commands/add.txt +10 -0
  48. package/docs/commands/board.txt +3 -1
  49. package/docs/commands/burndown.txt +2 -4
  50. package/docs/commands/edit.txt +22 -0
  51. package/docs/commands/find.txt +45 -1
  52. package/docs/commands/help.txt +1 -0
  53. package/docs/commands/move.txt +1 -1
  54. package/docs/commands/sort.txt +13 -2
  55. package/docs/commands/validate.txt +12 -0
  56. package/docs/filtering-and-sorting.md +218 -0
  57. package/docs/index-structure.md +68 -19
  58. package/docs/index.md +26 -2
  59. package/docs/migration-2.0.md +92 -0
  60. package/docs/quick-start.md +37 -1
  61. package/docs/task-structure.md +12 -3
  62. package/docs/views.md +229 -0
  63. package/example/README.md +70 -0
  64. package/example/advanced/.kanbn/index.md +26 -0
  65. package/example/advanced/.kanbn/tasks/add-rate-limiting.md +18 -0
  66. package/example/advanced/.kanbn/tasks/add-sso-support.md +15 -0
  67. package/example/advanced/.kanbn/tasks/migrate-to-new-cdn.md +14 -0
  68. package/example/advanced/.kanbn/tasks/refresh-marketing-site.md +14 -0
  69. package/example/advanced/.kanbn/tasks/rotate-api-keys.md +15 -0
  70. package/example/advanced/.kanbn/tasks/split-billing-service.md +17 -0
  71. package/example/advanced/.kanbn/tasks/upgrade-node-runtime.md +19 -0
  72. package/example/advanced/kanbn.yml +59 -0
  73. package/example/views/.kanbn/index.md +140 -0
  74. package/example/views/.kanbn/tasks/add-audit-log-export.md +18 -0
  75. package/example/views/.kanbn/tasks/add-dark-mode-toggle.md +16 -0
  76. package/example/views/.kanbn/tasks/build-webhook-retry-queue.md +15 -0
  77. package/example/views/.kanbn/tasks/fix-avatar-upload-crash.md +13 -0
  78. package/example/views/.kanbn/tasks/fix-expired-session-redirect.md +15 -0
  79. package/example/views/.kanbn/tasks/investigate-offline-mode.md +12 -0
  80. package/example/views/.kanbn/tasks/rewrite-search-indexer.md +12 -0
  81. package/example/views/.kanbn/tasks/tidy-up-settings-copy.md +12 -0
  82. package/package.json +4 -3
  83. package/routes/edit.json +2 -1
  84. package/routes/validate.json +4 -2
  85. package/skills/kanbn-plan/references/index-structure.md +1 -0
  86. package/skills/kanbn-plan/references/task-structure.md +2 -0
  87. package/src/board.js +1 -0
  88. package/src/controller/board.js +6 -0
  89. package/src/controller/edit.js +65 -12
  90. package/src/controller/gantt.js +46 -1
  91. package/src/controller/status.js +12 -0
  92. package/src/controller/task.js +1 -1
  93. package/src/controller/validate.js +78 -15
  94. package/src/main.js +324 -152
  95. package/src/parse-index.js +3 -0
  96. package/src/parse-markdown.js +3 -1
  97. package/src/parse-task.js +28 -1
  98. package/src/utility.js +26 -1
  99. /package/example/{.kanbn → basic/.kanbn}/index.md +0 -0
  100. /package/example/{.kanbn → basic/.kanbn}/tasks/add-basic-activity-feed.md +0 -0
  101. /package/example/{.kanbn → basic/.kanbn}/tasks/add-passwordless-login-option.md +0 -0
  102. /package/example/{.kanbn → basic/.kanbn}/tasks/add-usage-alert-email-thresholds.md +0 -0
  103. /package/example/{.kanbn → basic/.kanbn}/tasks/build-email-template-system.md +0 -0
  104. /package/example/{.kanbn → basic/.kanbn}/tasks/build-invoice-download-endpoint.md +0 -0
  105. /package/example/{.kanbn → basic/.kanbn}/tasks/build-tenant-settings-page.md +0 -0
  106. /package/example/{.kanbn → basic/.kanbn}/tasks/create-organization-switcher.md +0 -0
  107. /package/example/{.kanbn → basic/.kanbn}/tasks/create-sandbox-environment-provisioner.md +0 -0
  108. /package/example/{.kanbn → basic/.kanbn}/tasks/create-self-serve-cancellation-flow.md +0 -0
  109. /package/example/{.kanbn → basic/.kanbn}/tasks/define-product-pricing-strategy.md +0 -0
  110. /package/example/{.kanbn → basic/.kanbn}/tasks/design-onboarding-checklist.md +0 -0
  111. /package/example/{.kanbn → basic/.kanbn}/tasks/design-team-invite-expiry-flow.md +0 -0
  112. /package/example/{.kanbn → basic/.kanbn}/tasks/implement-data-retention-policy-jobs.md +0 -0
  113. /package/example/{.kanbn → basic/.kanbn}/tasks/implement-feature-flags-foundation.md +0 -0
  114. /package/example/{.kanbn → basic/.kanbn}/tasks/implement-project-creation-wizard.md +0 -0
  115. /package/example/{.kanbn → basic/.kanbn}/tasks/implement-stripe-webhook-signature-check.md +0 -0
  116. /package/example/{.kanbn → basic/.kanbn}/tasks/implement-team-permissions-ui.md +0 -0
  117. /package/example/{.kanbn → basic/.kanbn}/tasks/implement-user-signup-and-login.md +0 -0
  118. /package/example/{.kanbn → basic/.kanbn}/tasks/integrate-crm-lead-sync.md +0 -0
  119. /package/example/{.kanbn → basic/.kanbn}/tasks/legal-review-terms-and-privacy.md +0 -0
  120. /package/example/{.kanbn → basic/.kanbn}/tasks/migrate-legacy-events-to-new-schema.md +0 -0
  121. /package/example/{.kanbn → basic/.kanbn}/tasks/optimize-dashboard-first-load.md +0 -0
  122. /package/example/{.kanbn → basic/.kanbn}/tasks/prototype-report-export-scheduler.md +0 -0
  123. /package/example/{.kanbn → basic/.kanbn}/tasks/publish-internal-qa-checklist.md +0 -0
  124. /package/example/{.kanbn → basic/.kanbn}/tasks/setup-ci-pipeline.md +0 -0
package/docs/views.md ADDED
@@ -0,0 +1,229 @@
1
+ # Views
2
+
3
+ A view is a saved board layout. Views let you re-arrange, filter and group the same set of tasks without changing the index columns or moving any tasks around.
4
+
5
+ Views are defined in the `views` project option (index front matter, or `kanbn.json` / `kanbn.yml` — see [Advanced Configuration](advanced-configuration.md)) and are selected with:
6
+
7
+ ```bash
8
+ kanbn board --view "view name"
9
+ kanbn board -v "view name"
10
+ ```
11
+
12
+ If the named view doesn't exist, `kanbn board` reports an error. Running `kanbn board` with no `--view` option always uses the [default board](#the-default-board), even if a view called `default` exists.
13
+
14
+ A working example lives in [`example/views`](../example/views).
15
+
16
+ ## Structure
17
+
18
+ ```yaml
19
+ views:
20
+ - name: 'View name' # required
21
+ filters: {} # optional, applied to every task before columns and lanes
22
+ columns: # optional, at least 1 entry if present
23
+ - name: 'Column name' # required, this is the board heading
24
+ filters: {} # optional
25
+ sorters: [] # optional
26
+ lanes: # optional
27
+ - name: 'Lane name' # required
28
+ filters: {} # optional
29
+ ```
30
+
31
+ | Property | Where | Required | Description |
32
+ | --- | --- | --- | --- |
33
+ | `name` | view | yes | The name passed to `kanbn board --view`. If two views share a name, the first one wins |
34
+ | `filters` | view | no | A [filter set](filtering-and-sorting.md#filters) applied to all tasks before anything else |
35
+ | `columns` | view | no | The board columns, left to right. Defaults to the index columns |
36
+ | `columns[].name` | column | yes | The column heading. It does **not** have to be an index column name |
37
+ | `columns[].filters` | column | no | A [filter set](filtering-and-sorting.md#filters) deciding which tasks appear in this column |
38
+ | `columns[].sorters` | column | no | A [sorter list](filtering-and-sorting.md#sorters) for tasks in this column |
39
+ | `lanes` | view | no | Horizontal swimlanes, top to bottom. Defaults to a single lane called "All tasks" |
40
+ | `lanes[].name` | lane | yes | The lane label |
41
+ | `lanes[].filters` | lane | no | A [filter set](filtering-and-sorting.md#filters) applied to every column in this lane |
42
+
43
+ Anything else is ignored. In particular there is **no** `hidden` property on view columns — to leave a column out of a view, just don't list it.
44
+
45
+ ## How a view is built
46
+
47
+ For every lane, and for every column in that lane, Kanbn takes the full list of tracked tasks and:
48
+
49
+ 1. applies the view's root `filters` (if any);
50
+ 2. merges the column's `filters` with the lane's `filters` and applies the result;
51
+ 3. sorts what's left using the column's `sorters`.
52
+
53
+ The merge in step 2 is a shallow object merge with the **lane winning**: if a column and a lane both filter on the same field, the lane's value is used. Filters on different fields combine with AND.
54
+
55
+ Two consequences worth knowing:
56
+
57
+ - **A column with no `filters` shows every task**, in every lane, regardless of which index column the tasks are actually in. Column names in a view are just labels. If you want a view column to show one index column, filter on it explicitly:
58
+
59
+ ```yaml
60
+ - name: 'In Progress'
61
+ filters:
62
+ column: 'In Progress'
63
+ ```
64
+
65
+ - **Views can overlap.** The same task can appear in more than one column or lane if it matches more than one filter set. That's often what you want (a "Bugs" and an "Overdue" column side by side), but it does mean a view is not necessarily a partition of the board.
66
+
67
+ ## The default board
68
+
69
+ When a view doesn't define `columns`, Kanbn builds them from the index: one column per index column, in index order, each filtered to `column: <that column name>`, and [`hiddenColumns`](index-structure.md#hiddencolumns) removed.
70
+
71
+ `hiddenColumns` is only consulted when building this default column list. **A view that defines its own `columns` ignores `hiddenColumns` entirely**, so a view is also the way to see hidden columns:
72
+
73
+ ```yaml
74
+ views:
75
+ - name: 'everything'
76
+ columns:
77
+ - name: 'All tasks (including hidden columns)'
78
+ sorters:
79
+ - field: column
80
+ order: ascending
81
+ ```
82
+
83
+ When a view doesn't define `lanes` (or defines an empty list), a single lane called "All tasks" is used.
84
+
85
+ ## Lanes
86
+
87
+ A lane is a horizontal band across the whole board. Every column is rendered once per lane, filtered by that lane's filters. Lanes are for grouping the same columns by some secondary dimension: assignee, tag, workload, priority, and so on.
88
+
89
+ ```yaml
90
+ views:
91
+ - name: 'by-assignee'
92
+ columns:
93
+ - name: 'Backlog'
94
+ filters:
95
+ column: 'Backlog'
96
+ - name: 'In Progress'
97
+ filters:
98
+ column: 'In Progress'
99
+ - name: 'Done'
100
+ filters:
101
+ column: 'Done'
102
+ lanes:
103
+ - name: 'Ana'
104
+ filters:
105
+ assigned: '^Ana$'
106
+ - name: 'Ben'
107
+ filters:
108
+ assigned: '^Ben$'
109
+ - name: 'Unassigned'
110
+ filters:
111
+ assigned: '^$'
112
+ ```
113
+
114
+ ```
115
+ ╭──────────────────────┬──────────────────────┬──────────────────────╮
116
+ │Backlog │» In Progress │✓ Done │
117
+ ├──────────────────────┼──────────────────────┼──────────────────────┤
118
+ │Ana │ │ │
119
+ ├──────────────────────┼──────────────────────┼──────────────────────┤
120
+ │Add Audit Log Export │Fix Expired Session │Add Dark Mode Toggle │
121
+ │ │Redirect │ │
122
+ ├──────────────────────┼──────────────────────┼──────────────────────┤
123
+ │Ben │ │ │
124
+ ├──────────────────────┼──────────────────────┼──────────────────────┤
125
+ │Fix Avatar Upload │Build Webhook Retry │ │
126
+ │Crash │Queue │ │
127
+ ├──────────────────────┼──────────────────────┼──────────────────────┤
128
+ │Unassigned │ │ │
129
+ ├──────────────────────┼──────────────────────┼──────────────────────┤
130
+ │Rewrite Search │ │ │
131
+ │Indexer │ │ │
132
+ │ │ │ │
133
+ │Tidy Up Settings Copy │ │ │
134
+ ╰──────────────────────┴──────────────────────┴──────────────────────╯
135
+ ```
136
+
137
+ Because `assigned` is a [string filter](filtering-and-sorting.md#string-filters) matched as a regex, `'^Ana$'` matches only tasks assigned to exactly "Ana" (a bare `Ana` would also match "Ana-Maria"), and `'^$'` matches unassigned tasks, whose `assigned` value is treated as an empty string.
138
+
139
+ *Note: a task that matches no lane filter simply isn't shown. Lanes don't have a catch-all.*
140
+
141
+ ## Examples
142
+
143
+ All of these are in [`example/views/.kanbn/index.md`](../example/views/.kanbn/index.md) and can be run from the `example/views` directory.
144
+
145
+ ### Group by workload
146
+
147
+ Columns as workload buckets, lanes splitting started from not-started work. Neither the columns nor the lanes correspond to index columns:
148
+
149
+ ```yaml
150
+ - name: 'workload'
151
+ columns:
152
+ - name: 'Small (1-2)'
153
+ filters:
154
+ workload: [1, 2]
155
+ - name: 'Medium (3-5)'
156
+ filters:
157
+ workload: [3, 5]
158
+ - name: 'Large (6+)'
159
+ filters:
160
+ workload: [6, 99]
161
+ lanes:
162
+ - name: 'Not started'
163
+ filters:
164
+ column: 'Backlog'
165
+ - name: 'Started'
166
+ filters:
167
+ column: 'In Progress'
168
+ ```
169
+
170
+ ### Root filter plus per-column sorting
171
+
172
+ The root `filters` narrows the whole view to bugs; the first column narrows further by due date and sorts by workload; the second column has no filters, so within this view it shows all bugs:
173
+
174
+ ```yaml
175
+ - name: 'triage'
176
+ filters:
177
+ tag: Bug
178
+ columns:
179
+ - name: 'Due before Aug 2026'
180
+ filters:
181
+ due:
182
+ - 2020-01-01
183
+ - 2026-08-01
184
+ sorters:
185
+ - field: workload
186
+ order: descending
187
+ - name: 'All bugs'
188
+ sorters:
189
+ - field: name
190
+ order: ascending
191
+ ```
192
+
193
+ ## Inspecting a view
194
+
195
+ `kanbn board --json` (with or without `--view`) prints the resolved board rather than rendering it, which is the quickest way to check that a view's filters do what you expect:
196
+
197
+ ```bash
198
+ kanbn board -v triage --json
199
+ ```
200
+
201
+ ```json
202
+ {
203
+ "headings": [
204
+ { "name": "Due before Aug 2026", "heading": "^:^+Due before Aug 2026^:" },
205
+ { "name": "All bugs", "heading": "^:^+All bugs^:" }
206
+ ],
207
+ "lanes": [
208
+ {
209
+ "name": "All tasks",
210
+ "columns": [
211
+ [
212
+ { "id": "fix-expired-session-redirect", "workload": 3, "...": "..." },
213
+ { "id": "fix-avatar-upload-crash", "workload": 2, "...": "..." }
214
+ ],
215
+ [
216
+ { "id": "fix-avatar-upload-crash", "...": "..." },
217
+ { "id": "fix-expired-session-redirect", "...": "..." }
218
+ ]
219
+ ]
220
+ }
221
+ ]
222
+ }
223
+ ```
224
+
225
+ ## Limitations
226
+
227
+ - View column `sorters` accept the same fields as `kanbn sort` and `columnSorting`, plus `column`. See [sortable fields](filtering-and-sorting.md#sortable-fields).
228
+ - Views only affect `kanbn board`. `kanbn find`, `kanbn status`, `kanbn burndown`, `kanbn gantt` and `kanbn history` don't take a `--view` option.
229
+ - Views are read-only: `kanbn move` and `kanbn add` still work in terms of index columns, not view columns.
@@ -0,0 +1,70 @@
1
+ # Kanbn Examples
2
+
3
+ Each subdirectory is a self-contained Kanbn workspace. `cd` into one and run any Kanbn command
4
+ against it — nothing here affects the boards in the other directories.
5
+
6
+ ```bash
7
+ cd example/views
8
+ kanbn board -v by-assignee
9
+ ```
10
+
11
+ The index and config files in these examples are commented so they can be read as documentation.
12
+ Kanbn rewrites those files whenever it saves (`kanbn add`, `kanbn move`, `kanbn sort --save`,
13
+ `kanbn validate --save`, ...), which reformats the YAML and strips the comments — so run mutating
14
+ commands on a copy if you want to keep them.
15
+
16
+ ## [`basic`](basic)
17
+
18
+ A typical in-flight product board. Demonstrates the core setup you get from `kanbn init`:
19
+
20
+ - columns, with `startedColumns` and `completedColumns`
21
+ - tags and `taskWorkloadTags` for workload calculation
22
+ - `sprints`
23
+ - tasks with sub-tasks, `assigned`, `progress`, `due` and `## History` sections
24
+
25
+ ```bash
26
+ kanbn board
27
+ kanbn status --due
28
+ kanbn burndown -p "Workflow Sprint"
29
+ kanbn gantt
30
+ ```
31
+
32
+ ## [`views`](views)
33
+
34
+ Custom board layouts. See [Views](../docs/views.md).
35
+
36
+ - `default` — the index columns, spelled out explicitly
37
+ - `by-assignee` — the same columns, split into one lane per assignee plus an "Unassigned" lane
38
+ - `triage` — a root filter narrowing the whole view to bugs, plus per-column filters and sorters
39
+ - `workload` — columns as workload buckets and lanes as started/not-started
40
+ - `everything` — a single column showing every task, including the hidden `Icebox` column
41
+
42
+ ```bash
43
+ kanbn board
44
+ kanbn board -v by-assignee
45
+ kanbn board -v triage
46
+ kanbn board -v workload
47
+ kanbn board -v everything
48
+ kanbn board -v triage --json
49
+ ```
50
+
51
+ ## [`advanced`](advanced)
52
+
53
+ Project configuration beyond the defaults. See
54
+ [Advanced Configuration](../docs/advanced-configuration.md).
55
+
56
+ - all project options live in [`kanbn.yml`](advanced/kanbn.yml) instead of the index front matter
57
+ - `customFields` (`team`, `storyPoints`, `needsDesign`, `reviewedAt`) that can be set, searched and sorted
58
+ - `reviewedAtColumns`, which stamps `reviewedAt` the first time a task enters the `Review` column
59
+ - `columnSorting`, which keeps `Backlog` sorted by workload in the index file itself
60
+ - a custom `taskTemplate` and `dateFormat`
61
+ - a hidden `Blocked` column
62
+
63
+ ```bash
64
+ kanbn board
65
+ kanbn find --team Platform
66
+ kanbn find --storyPoints 3 --storyPoints 8
67
+ kanbn find --needsDesign
68
+ kanbn find --no-needsDesign
69
+ kanbn sort "Backlog" --workload -z --name -a --save
70
+ ```
@@ -0,0 +1,26 @@
1
+ # Advanced Example
2
+
3
+ Project options for this board live in `kanbn.yml` in the workspace root rather
4
+ than in this file's front matter. See `docs/advanced-configuration.md`.
5
+
6
+ ## Backlog
7
+
8
+ - [add-sso-support](tasks/add-sso-support.md)
9
+ - [refresh-marketing-site](tasks/refresh-marketing-site.md)
10
+ - [rotate-api-keys](tasks/rotate-api-keys.md)
11
+
12
+ ## In Progress
13
+
14
+ - [split-billing-service](tasks/split-billing-service.md)
15
+
16
+ ## Review
17
+
18
+ - [add-rate-limiting](tasks/add-rate-limiting.md)
19
+
20
+ ## Done
21
+
22
+ - [upgrade-node-runtime](tasks/upgrade-node-runtime.md)
23
+
24
+ ## Blocked
25
+
26
+ - [migrate-to-new-cdn](tasks/migrate-to-new-cdn.md)
@@ -0,0 +1,18 @@
1
+ ---
2
+ created: 2026-06-25T09:00:00.000Z
3
+ updated: 2026-07-18T09:00:00.000Z
4
+ started: 2026-07-08T09:00:00.000Z
5
+ reviewedAt: 2026-07-18T09:00:00.000Z
6
+ assigned: Ana
7
+ progress: 0.9
8
+ due: 2026-07-20T17:00:00.000Z
9
+ team: Platform
10
+ storyPoints: 3
11
+ needsDesign: false
12
+ tags:
13
+ - Medium
14
+ ---
15
+
16
+ # Add Rate Limiting
17
+
18
+ Per-tenant rate limits on the public API.
@@ -0,0 +1,15 @@
1
+ ---
2
+ created: 2026-07-01T09:00:00.000Z
3
+ updated: 2026-07-01T09:00:00.000Z
4
+ assigned: Ana
5
+ due: 2026-11-01T17:00:00.000Z
6
+ team: Identity
7
+ storyPoints: 13
8
+ needsDesign: true
9
+ tags:
10
+ - Huge
11
+ ---
12
+
13
+ # Add SSO Support
14
+
15
+ Support SAML and OIDC single sign-on for enterprise customers.
@@ -0,0 +1,14 @@
1
+ ---
2
+ created: 2026-06-10T09:00:00.000Z
3
+ updated: 2026-07-01T09:00:00.000Z
4
+ due: 2026-12-01T17:00:00.000Z
5
+ team: Platform
6
+ storyPoints: 5
7
+ needsDesign: false
8
+ tags:
9
+ - Large
10
+ ---
11
+
12
+ # Migrate To New CDN
13
+
14
+ Blocked until the contract with the new CDN provider is signed.
@@ -0,0 +1,14 @@
1
+ ---
2
+ created: 2026-07-02T09:00:00.000Z
3
+ updated: 2026-07-02T09:00:00.000Z
4
+ due: 2026-09-15T17:00:00.000Z
5
+ team: Growth
6
+ storyPoints: 5
7
+ needsDesign: true
8
+ tags:
9
+ - Medium
10
+ ---
11
+
12
+ # Refresh Marketing Site
13
+
14
+ Rebuild the landing pages on the new design system.
@@ -0,0 +1,15 @@
1
+ ---
2
+ created: 2026-07-03T09:00:00.000Z
3
+ updated: 2026-07-03T09:00:00.000Z
4
+ assigned: Ben
5
+ due: 2026-08-01T17:00:00.000Z
6
+ team: Platform
7
+ storyPoints: 2
8
+ needsDesign: false
9
+ tags:
10
+ - Small
11
+ ---
12
+
13
+ # Rotate API Keys
14
+
15
+ Quarterly rotation of all outbound integration keys.
@@ -0,0 +1,17 @@
1
+ ---
2
+ created: 2026-06-20T09:00:00.000Z
3
+ updated: 2026-07-10T09:00:00.000Z
4
+ started: 2026-07-05T09:00:00.000Z
5
+ assigned: Ben
6
+ progress: 0.4
7
+ due: 2026-10-01T17:00:00.000Z
8
+ team: Platform
9
+ storyPoints: 8
10
+ needsDesign: false
11
+ tags:
12
+ - Large
13
+ ---
14
+
15
+ # Split Billing Service
16
+
17
+ Extract billing out of the monolith into its own service.
@@ -0,0 +1,19 @@
1
+ ---
2
+ created: 2026-06-01T09:00:00.000Z
3
+ updated: 2026-06-18T09:00:00.000Z
4
+ started: 2026-06-05T09:00:00.000Z
5
+ completed: 2026-06-18T09:00:00.000Z
6
+ reviewedAt: 2026-06-15T09:00:00.000Z
7
+ assigned: Ben
8
+ progress: 1
9
+ due: 2026-06-20T17:00:00.000Z
10
+ team: Platform
11
+ storyPoints: 3
12
+ needsDesign: false
13
+ tags:
14
+ - Medium
15
+ ---
16
+
17
+ # Upgrade Node Runtime
18
+
19
+ Move all services onto the current Node LTS release.
@@ -0,0 +1,59 @@
1
+ # All project options for this board live in this file instead of the index front matter.
2
+ # Kanbn looks for `kanbn.json` or `kanbn.yml` in the root of the workspace.
3
+ #
4
+ # Note: Kanbn rewrites this file whenever it saves project options (for example
5
+ # `kanbn sort --save`), which strips these comments.
6
+
7
+ startedColumns:
8
+ - 'In Progress'
9
+ - Review
10
+ completedColumns:
11
+ - Done
12
+
13
+ # The Blocked column is hidden from the default board, but still tracked.
14
+ # Any view that defines its own columns can still show it.
15
+ hiddenColumns:
16
+ - Blocked
17
+
18
+ defaultTaskWorkload: 2
19
+ taskWorkloadTags:
20
+ Tiny: 1
21
+ Small: 2
22
+ Medium: 3
23
+ Large: 5
24
+ Huge: 8
25
+
26
+ # Extra metadata fields. Once declared here they can be set with `kanbn add`
27
+ # and `kanbn edit`, searched with `kanbn find`, sorted with `kanbn sort`,
28
+ # filtered in views, and interpolated into taskTemplate.
29
+ customFields:
30
+ - name: team
31
+ type: string
32
+ - name: storyPoints
33
+ type: number
34
+ - name: needsDesign
35
+ type: boolean
36
+ - name: reviewedAt
37
+ type: date
38
+ updateDate: once
39
+
40
+ # `reviewedAt` is stamped the first time a task enters the Review column
41
+ # (`updateDate: once`). Use `always` to re-stamp on every move.
42
+ reviewedAtColumns:
43
+ - Review
44
+
45
+ # The Backlog column is kept sorted in the index file itself, so the order
46
+ # survives `kanbn add`, `kanbn move` and `kanbn validate --save`.
47
+ columnSorting:
48
+ Backlog:
49
+ - field: workload
50
+ order: descending
51
+ - field: name
52
+ order: ascending
53
+
54
+ dateFormat: yyyy-mm-dd
55
+
56
+ # Custom fields (team, storyPoints, ...) can be interpolated here because they
57
+ # are declared in customFields above. See docs/index-structure.md for the full
58
+ # list of available variables.
59
+ taskTemplate: "^+^_${overdue ? '^R' : ''}${name}^:${assigned ? ('\\n^-@' + assigned) : ''}${team ? ('\\n^-' + team) : ''}${storyPoints ? ('\\n^-' + storyPoints + 'pts') : ''}${due ? ('\\n^-due ' + due) : ''}"
@@ -0,0 +1,140 @@
1
+ ---
2
+ startedColumns:
3
+ - 'In Progress'
4
+ completedColumns:
5
+ - Done
6
+ hiddenColumns:
7
+ - Icebox
8
+ taskWorkloadTags:
9
+ Tiny: 1
10
+ Small: 2
11
+ Medium: 3
12
+ Large: 5
13
+ Huge: 8
14
+ views:
15
+
16
+ # The index columns, spelled out explicitly. Note that a view column with no
17
+ # filters would show *every* task, not the tasks in a column of that name.
18
+ - name: 'default'
19
+ columns:
20
+ - name: 'Backlog'
21
+ filters:
22
+ column: 'Backlog'
23
+ - name: 'In Progress'
24
+ filters:
25
+ column: 'In Progress'
26
+ - name: 'Done'
27
+ filters:
28
+ column: 'Done'
29
+
30
+ # The same columns, grouped into one lane per assignee.
31
+ # Lane filters are merged over each column's filters.
32
+ - name: 'by-assignee'
33
+ columns:
34
+ - name: 'Backlog'
35
+ filters:
36
+ column: 'Backlog'
37
+ - name: 'In Progress'
38
+ filters:
39
+ column: 'In Progress'
40
+ - name: 'Done'
41
+ filters:
42
+ column: 'Done'
43
+ lanes:
44
+ - name: 'Ana'
45
+ filters:
46
+ assigned: '^Ana$'
47
+ - name: 'Ben'
48
+ filters:
49
+ assigned: '^Ben$'
50
+ - name: 'Unassigned'
51
+ filters:
52
+ assigned: '^$'
53
+
54
+ # A root filter narrows the whole view to bugs before columns are built.
55
+ # The second column has no filters, so within this view it shows all bugs.
56
+ - name: 'triage'
57
+ filters:
58
+ tag: Bug
59
+ columns:
60
+ - name: 'Due before Aug 2026'
61
+ filters:
62
+ due:
63
+ - 2020-01-01
64
+ - 2026-08-01
65
+ sorters:
66
+ - field: workload
67
+ order: descending
68
+ - name: 'All bugs'
69
+ sorters:
70
+ - field: name
71
+ order: ascending
72
+
73
+ # Columns and lanes don't have to correspond to index columns at all.
74
+ - name: 'workload'
75
+ columns:
76
+ - name: 'Small (1-2)'
77
+ filters:
78
+ workload:
79
+ - 1
80
+ - 2
81
+ - name: 'Medium (3-5)'
82
+ filters:
83
+ workload:
84
+ - 3
85
+ - 5
86
+ - name: 'Large (6+)'
87
+ filters:
88
+ workload:
89
+ - 6
90
+ - 99
91
+ lanes:
92
+ - name: 'Not started'
93
+ filters:
94
+ column: 'Backlog'
95
+ - name: 'Started'
96
+ filters:
97
+ column: 'In Progress'
98
+
99
+ # A view that defines its own columns ignores hiddenColumns, so this one
100
+ # also shows tasks in the hidden Icebox column.
101
+ - name: 'everything'
102
+ columns:
103
+ - name: 'All tasks (including Icebox)'
104
+ sorters:
105
+ - field: column
106
+ order: ascending
107
+ - field: name
108
+ order: ascending
109
+ ---
110
+
111
+ # Views Example
112
+
113
+ A small board used to demonstrate views, lanes, filters and sorters. Try:
114
+
115
+ - `kanbn board`
116
+ - `kanbn board -v default`
117
+ - `kanbn board -v by-assignee`
118
+ - `kanbn board -v triage`
119
+ - `kanbn board -v workload`
120
+ - `kanbn board -v everything`
121
+
122
+ ## Backlog
123
+
124
+ - [add-audit-log-export](tasks/add-audit-log-export.md)
125
+ - [fix-avatar-upload-crash](tasks/fix-avatar-upload-crash.md)
126
+ - [rewrite-search-indexer](tasks/rewrite-search-indexer.md)
127
+ - [tidy-up-settings-copy](tasks/tidy-up-settings-copy.md)
128
+
129
+ ## In Progress
130
+
131
+ - [fix-expired-session-redirect](tasks/fix-expired-session-redirect.md)
132
+ - [build-webhook-retry-queue](tasks/build-webhook-retry-queue.md)
133
+
134
+ ## Done
135
+
136
+ - [add-dark-mode-toggle](tasks/add-dark-mode-toggle.md)
137
+
138
+ ## Icebox
139
+
140
+ - [investigate-offline-mode](tasks/investigate-offline-mode.md)
@@ -0,0 +1,18 @@
1
+ ---
2
+ created: 2026-07-02T09:00:00.000Z
3
+ updated: 2026-07-02T09:00:00.000Z
4
+ assigned: Ana
5
+ due: 2026-09-30T17:00:00.000Z
6
+ tags:
7
+ - Feature
8
+ - Medium
9
+ ---
10
+
11
+ # Add Audit Log Export
12
+
13
+ Let admins download an audit log as CSV.
14
+
15
+ ## Sub-tasks
16
+
17
+ - [ ] Add an export endpoint
18
+ - [ ] Add a download button to the audit log page
@@ -0,0 +1,16 @@
1
+ ---
2
+ created: 2026-06-20T09:00:00.000Z
3
+ updated: 2026-07-01T09:00:00.000Z
4
+ started: 2026-06-22T09:00:00.000Z
5
+ completed: 2026-07-01T09:00:00.000Z
6
+ assigned: Ana
7
+ progress: 1
8
+ due: 2026-07-01T17:00:00.000Z
9
+ tags:
10
+ - Feature
11
+ - Small
12
+ ---
13
+
14
+ # Add Dark Mode Toggle
15
+
16
+ Add a dark mode toggle to the account menu.