Skip to content

Commit 7664743

Browse files
committed
[green] persist bounded current text with atomic Drift checkpoints
Signed-off-by: Viwat Vchirawongkwin <viwat.v@chula.ac.th>
1 parent 628b56f commit 7664743

11 files changed

Lines changed: 3051 additions & 58 deletions

‎app/DEPENDENCIES.md‎

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ Toolchain pin: **Flutter 3.44.1 (stable)** / Dart SDK `^3.12.1` (see
4444
| `http` | runtime | `^1.6.0` | 1.6.0 | BSD-3-Clause | The bounded public GitHub REST client for the connected A-33 subset ([ADR-0040](../docs/decisions/0040-sha-pinned-connected-github-import.md)). The direct dependency is confined to `lib/github_import/`'s production composition point and `GithubRepositoryClient`; all feature consumers bind to the neutral `GithubApi` seam. The adapter accepts only canonical public repository input, sends no credential or user source, permits requests only to exact HTTPS host `api.github.com`, disables redirects, pins every browse to a full commit SHA, and bounds time and response bodies. Min 1.6.0 supplies the abortable request surface used by the cancellation contract on the pinned Dart/Flutter toolchain. |
4545
| `highlight` | runtime | `^0.7.0` | 0.7.0 | MIT | Python grammar data consumed directly by `lib/editor`'s rich adapter (A-20). It also appears in `flutter_code_editor`'s closure, but PyBLE's direct import makes the dependency and compatible minimum explicit under BLD-2. |
4646
| `webview_flutter` | runtime | `^4.14.1` | 4.14.1 | BSD-3-Clause | The offline platform-WebView host for the pinned Blockly runtime (A-31, ADR-0013). Min 4.14.1 is compatible with PyBLE's Android 24 / iOS 15 platform floors and supplies `loadFlutterAsset`, JavaScript channels, and navigation delegates. Its sole importer is `lib/blocks/`; generated source and board actions stay in Dart behind the neutral `Connection` seam. |
47+
| `drift` | runtime | `^2.35.3` | 2.35.3 | MIT | ADR-0048 bounded current-text recovery. Typed atomic SQLite transactions and owned background native executor; no second persistence backend. |
48+
| `sqlite3` | runtime | `3.5.0` (exact) | 3.5.0 | MIT | Native SQLite bindings/build hooks used by Drift; exact compatibility ceiling for Flutter 3.44.1's pinned `meta` 1.18.0. Later sqlite3 releases require newer hooks/meta; no dependency override is used. SQLite itself is public domain; default upstream SQLite build, no sqlite3mc/encryption fork. |
49+
| `crypto` | runtime | `^3.0.8` | 3.0.8 | BSD-3-Clause | Exact UTF-8 SHA-256 identity checks for local recovery; accidental corruption detection, never board authority or authenticity. Promoted from transitive to explicit direct dependency. |
50+
| `path_provider` | runtime | `^2.1.6` | 2.1.6 | BSD-3-Clause | Resolves the app-private persistent Application Support directory for the single Drift store. No temp/cache/external storage, source upload or remote sync. |
51+
| `drift_dev` | dev | `^2.35.2` | 2.35.2 | MIT | Typed table generation and initial v1 schema export; build-time only. |
52+
| `build_runner` | dev | `^2.15.1` | 2.15.1 | BSD-3-Clause | Reproducible Drift source generation. Resolved with the pinned SDK/meta without overrides; build-time only. |
4753
| `flutter_test` | dev (SDK) | Flutter SDK | 3.44.1 | BSD-3-Clause | Widget/unit/golden test harness; the substrate for the G1 suites (NFR-MAINT-4). |
4854
| `integration_test` | dev (SDK) | Flutter SDK | 3.44.1 | BSD-3-Clause | On-device Android/iPadOS parity coverage for the real Blockly platform WebView, local asset load, JavaScript bridge, generated Python, and file-backed actions (A-31). Ships with the Flutter SDK and is never part of a release build. |
4955
| `flutter_lints` | dev | `^6.0.0` | 6.0.0 | BSD-3-Clause | Recommended Flutter lint set, activated via `analysis_options.yaml`; the static-analysis floor for the app CI gate. Toolchain-default major for Flutter 3.44.1. |
@@ -68,7 +74,6 @@ below the table.
6874
| `charcode` | 1.4.0 | BSD-3-Clause |
6975
| `clock` | 1.1.2 | Apache-2.0 |
7076
| `collection` | 1.19.1 | BSD-3-Clause |
71-
| `crypto` | 3.0.7 | BSD-3-Clause |
7277
| `dbus` `‡` | 0.7.14 | MPL-2.0 |
7378
| `equatable` | 2.1.0 | MIT |
7479
| `fake_async` | 1.3.3 | Apache-2.0 |
@@ -133,6 +138,64 @@ below the table.
133138
| `win32` | 6.3.0 | BSD-3-Clause |
134139
| `xml` | 6.6.1 | MIT |
135140

141+
### Recovery dependency additions (PYB-006.2)
142+
143+
These additional locked transitive packages were checked against the exact package
144+
`LICENSE` files on 31 October 2026. Build generators, analyzer and their helper
145+
packages are development inputs; platform adapters compile only for their target.
146+
The original transitive table plus this table covers the resolved graph.
147+
148+
| Package | Resolved | SPDX |
149+
|---|---|---|
150+
| `_fe_analyzer_shared` | 100.0.0 | BSD-3-Clause |
151+
| `analyzer` | 13.0.0 | BSD-3-Clause |
152+
| `build` | 4.0.7 | BSD-3-Clause |
153+
| `build_config` | 1.3.3 | BSD-3-Clause |
154+
| `build_daemon` | 4.1.7 | BSD-3-Clause |
155+
| `built_collection` | 5.1.2 | BSD-3-Clause |
156+
| `built_value` | 8.13.0 | BSD-3-Clause |
157+
| `checked_yaml` | 2.0.4 | BSD-3-Clause |
158+
| `cli_util` | 0.6.0 | BSD-3-Clause |
159+
| `code_assets` | 1.2.1 | BSD-3-Clause |
160+
| `convert` | 3.1.2 | BSD-3-Clause |
161+
| `dart_style` | 3.1.9 | BSD-3-Clause |
162+
| `fixnum` | 1.1.1 | BSD-3-Clause |
163+
| `glob` | 2.2.0 | BSD-3-Clause |
164+
| `graphs` | 2.3.2 | BSD-3-Clause |
165+
| `hooks` | 2.0.2 | BSD-3-Clause |
166+
| `http_multi_server` | 3.2.3 | BSD-3-Clause |
167+
| `io` | 1.1.0 | BSD-3-Clause |
168+
| `jni` | 1.1.1 | BSD-3-Clause |
169+
| `jni_flutter` | 1.0.4+1 | BSD-3-Clause |
170+
| `jni_util` | 1.0.0 | BSD-3-Clause |
171+
| `json_annotation` | 4.12.0 | BSD-3-Clause |
172+
| `logging` | 1.3.0 | BSD-3-Clause |
173+
| `mime` | 2.1.0 | BSD-3-Clause |
174+
| `native_toolchain_c` | 0.19.2 | BSD-3-Clause |
175+
| `objective_c` | 9.5.0 | BSD-3-Clause |
176+
| `package_config` | 2.2.0 | BSD-3-Clause |
177+
| `path_provider_android` | 2.3.1 | BSD-3-Clause |
178+
| `path_provider_foundation` | 2.6.0 | BSD-3-Clause |
179+
| `path_provider_linux` | 2.2.2 | BSD-3-Clause |
180+
| `path_provider_platform_interface` | 2.1.3 | BSD-3-Clause |
181+
| `path_provider_windows` | 2.3.0 | BSD-3-Clause |
182+
| `pool` | 1.5.3 | BSD-3-Clause |
183+
| `pub_semver` | 2.2.1 | BSD-3-Clause |
184+
| `pubspec_parse` | 1.7.0 | BSD-3-Clause |
185+
| `recase` | 4.1.0 | BSD-2-Clause |
186+
| `record_use` | 0.6.0 | BSD-3-Clause |
187+
| `shelf` | 1.4.3 | BSD-3-Clause |
188+
| `shelf_web_socket` | 3.0.0 | BSD-3-Clause |
189+
| `source_gen` | 4.2.4 | BSD-3-Clause |
190+
| `sqlparser` | 0.45.1 | MIT |
191+
| `stream_transform` | 2.1.2 | BSD-3-Clause |
192+
| `watcher` | 1.2.1 | BSD-3-Clause |
193+
| `web_socket` | 1.0.1 | BSD-3-Clause |
194+
| `web_socket_channel` | 3.0.3 | BSD-3-Clause |
195+
| `xdg_directories` | 1.1.0 | BSD-3-Clause |
196+
| `yaml` | 3.1.4 | MIT |
197+
| `yaml_edit` | 2.2.4 | BSD-3-Clause |
198+
136199
### `†` Owner-ratified shipped carve-out — `autotrie` 2.0.0 (MPL-2.0)
137200

138201
`flutter_code_editor` constructs its autocomplete index with `autotrie`, even
@@ -205,6 +268,22 @@ rationale when added:
205268

206269
| Package | Sprint / story | Purpose |
207270
|---|---|---|
208-
| `drift`, `sqlite3` | S5 / A-24 | Local persistence. |
209271
| `fl_chart` | later | Plotting surface. |
210272
| `go_router` | — | Not planned for S1; navigation is index-based via a Riverpod `StateProvider` + `IndexedStack`. |
273+
274+
## Recovery build and notice reproduction
275+
276+
- Run `dart run build_runner build` from `app/`, then
277+
`dart run drift_dev schema dump lib/data/draft_database.dart drift_schemas/`.
278+
The first generated database source and schema are reviewed and committed;
279+
`build.yaml` preserves the authored-source SPDX preamble on regeneration.
280+
- Pub-package license texts remain in Flutter's mechanically generated
281+
`NOTICES.Z` and in-app LicenseRegistry. The SQLite native amalgamation's
282+
public-domain provenance is separately bundled in
283+
`assets/licenses/SQLite-PUBLIC-DOMAIN.txt`; PyBLE adds no custom SQLite code.
284+
- The default `sqlite3` build hook obtains its upstream binaries from the
285+
package's release assets, with the package-pinned SHA-256 checks. No binaries,
286+
compiler outputs or native signing inputs are committed here.
287+
- The database is `pyble.sqlite` in Application Support. Its `-wal`/`-shm`
288+
companions belong to the same store. Device/OS backup behavior is external
289+
to PyBLE's local checkpoint promise; no backup/sync feature is added.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
SQLite native database engine
2+
3+
SQLite is public-domain software, as documented by the SQLite project:
4+
https://www.sqlite.org/copyright.html
5+
6+
PyBLE uses the default SQLite engine supplied by the unmodified sqlite3 Dart
7+
package's build hook. The Dart bindings are separately MIT licensed; their
8+
license is included in Flutter's generated package notices. PyBLE does not
9+
ship the optional sqlite3mc engine.
10+
11+
Package provenance and locked versions: app/DEPENDENCIES.md and pubspec.lock.

‎app/build.yaml‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# SPDX-License-Identifier: MIT
2+
# Part of PyBLE (https://pyble.dev) — see /LICENSE.
3+
4+
targets:
5+
$default:
6+
builders:
7+
source_gen:combining_builder:
8+
options:
9+
preamble: |
10+
// SPDX-License-Identifier: MIT
11+
// Part of PyBLE (https://pyble.dev) — see /LICENSE.
Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
{
2+
"_meta": {
3+
"description": "This file contains a serialized version of schema entities for drift.",
4+
"version": "1.3.0"
5+
},
6+
"options": {
7+
"store_date_time_values_as_text": false
8+
},
9+
"entities": [
10+
{
11+
"id": 0,
12+
"references": [],
13+
"type": "table",
14+
"data": {
15+
"name": "projects",
16+
"was_declared_in_moor": false,
17+
"columns": [
18+
{
19+
"name": "id",
20+
"getter_name": "id",
21+
"moor_type": "string",
22+
"nullable": false,
23+
"customConstraints": null,
24+
"default_dart": null,
25+
"default_client_dart": null,
26+
"dsl_features": []
27+
},
28+
{
29+
"name": "name",
30+
"getter_name": "name",
31+
"moor_type": "string",
32+
"nullable": false,
33+
"customConstraints": null,
34+
"default_dart": null,
35+
"default_client_dart": null,
36+
"dsl_features": []
37+
},
38+
{
39+
"name": "created_at",
40+
"getter_name": "createdAt",
41+
"moor_type": "int",
42+
"nullable": false,
43+
"customConstraints": null,
44+
"default_dart": null,
45+
"default_client_dart": null,
46+
"dsl_features": []
47+
},
48+
{
49+
"name": "updated_at",
50+
"getter_name": "updatedAt",
51+
"moor_type": "int",
52+
"nullable": false,
53+
"customConstraints": null,
54+
"default_dart": null,
55+
"default_client_dart": null,
56+
"dsl_features": []
57+
}
58+
],
59+
"is_virtual": false,
60+
"without_rowid": false,
61+
"constraints": [],
62+
"explicit_pk": [
63+
"id"
64+
]
65+
}
66+
},
67+
{
68+
"id": 1,
69+
"references": [
70+
0
71+
],
72+
"type": "table",
73+
"data": {
74+
"name": "project_files",
75+
"was_declared_in_moor": false,
76+
"columns": [
77+
{
78+
"name": "id",
79+
"getter_name": "id",
80+
"moor_type": "string",
81+
"nullable": false,
82+
"customConstraints": null,
83+
"default_dart": null,
84+
"default_client_dart": null,
85+
"dsl_features": []
86+
},
87+
{
88+
"name": "project_id",
89+
"getter_name": "projectId",
90+
"moor_type": "string",
91+
"nullable": false,
92+
"customConstraints": null,
93+
"defaultConstraints": "REFERENCES projects (id)",
94+
"dialectAwareDefaultConstraints": {
95+
"sqlite": "REFERENCES projects (id)"
96+
},
97+
"default_dart": null,
98+
"default_client_dart": null,
99+
"dsl_features": [
100+
{
101+
"foreign_key": {
102+
"to": {
103+
"table": "projects",
104+
"column": "id"
105+
},
106+
"initially_deferred": false,
107+
"on_update": null,
108+
"on_delete": null
109+
}
110+
}
111+
]
112+
},
113+
{
114+
"name": "path",
115+
"getter_name": "path",
116+
"moor_type": "string",
117+
"nullable": false,
118+
"customConstraints": null,
119+
"default_dart": null,
120+
"default_client_dart": null,
121+
"dsl_features": []
122+
},
123+
{
124+
"name": "content",
125+
"getter_name": "content",
126+
"moor_type": "blob",
127+
"nullable": false,
128+
"customConstraints": null,
129+
"default_dart": null,
130+
"default_client_dart": null,
131+
"dsl_features": []
132+
},
133+
{
134+
"name": "size",
135+
"getter_name": "size",
136+
"moor_type": "int",
137+
"nullable": false,
138+
"customConstraints": null,
139+
"default_dart": null,
140+
"default_client_dart": null,
141+
"dsl_features": []
142+
},
143+
{
144+
"name": "content_hash",
145+
"getter_name": "contentHash",
146+
"moor_type": "string",
147+
"nullable": false,
148+
"customConstraints": null,
149+
"default_dart": null,
150+
"default_client_dart": null,
151+
"dsl_features": []
152+
},
153+
{
154+
"name": "updated_at",
155+
"getter_name": "updatedAt",
156+
"moor_type": "int",
157+
"nullable": false,
158+
"customConstraints": null,
159+
"default_dart": null,
160+
"default_client_dart": null,
161+
"dsl_features": []
162+
}
163+
],
164+
"is_virtual": false,
165+
"without_rowid": false,
166+
"constraints": [],
167+
"explicit_pk": [
168+
"id"
169+
]
170+
}
171+
},
172+
{
173+
"id": 2,
174+
"references": [],
175+
"type": "table",
176+
"data": {
177+
"name": "settings",
178+
"was_declared_in_moor": false,
179+
"columns": [
180+
{
181+
"name": "key",
182+
"getter_name": "key",
183+
"moor_type": "string",
184+
"nullable": false,
185+
"customConstraints": null,
186+
"default_dart": null,
187+
"default_client_dart": null,
188+
"dsl_features": []
189+
},
190+
{
191+
"name": "value",
192+
"getter_name": "value",
193+
"moor_type": "string",
194+
"nullable": false,
195+
"customConstraints": null,
196+
"default_dart": null,
197+
"default_client_dart": null,
198+
"dsl_features": []
199+
}
200+
],
201+
"is_virtual": false,
202+
"without_rowid": false,
203+
"constraints": [],
204+
"explicit_pk": [
205+
"key"
206+
]
207+
}
208+
}
209+
],
210+
"fixed_sql": [
211+
{
212+
"name": "projects",
213+
"sql": [
214+
{
215+
"dialect": "sqlite",
216+
"sql": "CREATE TABLE IF NOT EXISTS \"projects\" (\"id\" TEXT NOT NULL, \"name\" TEXT NOT NULL, \"created_at\" INTEGER NOT NULL, \"updated_at\" INTEGER NOT NULL, PRIMARY KEY (\"id\"));"
217+
}
218+
]
219+
},
220+
{
221+
"name": "project_files",
222+
"sql": [
223+
{
224+
"dialect": "sqlite",
225+
"sql": "CREATE TABLE IF NOT EXISTS \"project_files\" (\"id\" TEXT NOT NULL, \"project_id\" TEXT NOT NULL REFERENCES projects (id), \"path\" TEXT NOT NULL, \"content\" BLOB NOT NULL, \"size\" INTEGER NOT NULL, \"content_hash\" TEXT NOT NULL, \"updated_at\" INTEGER NOT NULL, PRIMARY KEY (\"id\"));"
226+
}
227+
]
228+
},
229+
{
230+
"name": "settings",
231+
"sql": [
232+
{
233+
"dialect": "sqlite",
234+
"sql": "CREATE TABLE IF NOT EXISTS \"settings\" (\"key\" TEXT NOT NULL, \"value\" TEXT NOT NULL, PRIMARY KEY (\"key\"));"
235+
}
236+
]
237+
}
238+
]
239+
}

‎app/lib/app/licenses.dart‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,10 @@ void registerBundledLicenses() {
2828
);
2929
yield LicenseEntryWithLineBreaks(<String>['Blockly'], text);
3030
});
31+
LicenseRegistry.addLicense(() async* {
32+
final String text = await rootBundle.loadString(
33+
'assets/licenses/SQLite-PUBLIC-DOMAIN.txt',
34+
);
35+
yield LicenseEntryWithLineBreaks(<String>['SQLite'], text);
36+
});
3137
}

0 commit comments

Comments
 (0)