Commit graph

1,071 commits

Author SHA1 Message Date
df99def5bc
feat(server): anonymous sign-in
People can sign in without an account: AnonymousIdpEndpoint exposes Serverpod's anonymous identity provider. lib/src/auth/auth_config.dart holds the token managers and identity providers, shared by server.dart and the tests, so the tests check what production runs. At most 30 new anonymous accounts per IP address and hour (Serverpod's default is 100): a school class behind one address can still start together, while one abuser gets at most 720 a day. No migration: the tables for anonymous accounts and rate limiting already exist.

Tests: signing in creates a person; the 31st account from one IP address within an hour is refused. They run without database rollback, since signing in uses concurrent transactions that the rollback can't wrap, and delete what they create instead.

The server switches off the lint rules for Dart v3.13's constructor syntax: Serverpod v4.0.2's code generator can't parse it yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-30 20:38:13 +02:00
518939ee84
chore(check): run the app's tests before every push
Now that the app has real tests, tool/check.sh runs them after the server tests, and AGENTS.md's checklist says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-30 20:38:13 +02:00
09a3904d4c
build(app): register the editor's plugins on macOS
Flutter regenerated the macOS plugin registrant for the two native plugins the editor brings, device_info_plus and file_picker_darwin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-30 20:38:13 +02:00
76130d311c
feat(app): rich content, its editor and one read-only view
RichContent (lib/src/core/content) keeps the editor's document JSON as a deeply unmodifiable copy plus a formatVersion; it is pure Dart and compared by value (equatable), so models and later the server can use it. fromJson refuses formats newer than the app knows. The name avoids a clash with Flutter's RichText widget.

lib/src/core/editor converts it to and from the editor's Document (a mutable deep copy on the way in, since the editor keeps and changes parts of the JSON it gets) and holds RichContentEditor, which reports every document change as new RichContent and opens empty content with a paragraph to type into, and RichContentView, the one read-only renderer, sized to its content with IntrinsicHeight as the editor's own example does for lists.

A placeholder screen edits a document and shows it again after storing it as JSON and reading it back. It keeps its state with setState because it is temporary; blocs come with the first real feature. AGENTS.md describes RichContent and equatable.

Tests: equality, immutability, the JSON round trip with Japanese text and marks, format checks, the round trip through the editor document including an edit, and the view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-30 20:38:12 +02:00
48fa4a7e44
build(app): the editor from our fork, and equatable
The app uses appflowy_editor from our fork of its main branch (01eccc6), moved to file_picker v13 and device_info_plus v13, so that everything in the pub workspace resolves to win32 v6, which Serverpod needs; the unchanged editor needs win32 v5. It is a local path until the fork is hosted, then a git URL pinned to a commit. equatable v3 provides value equality for models and states.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-30 20:38:12 +02:00
3f980c918c
refactor(app): Material from material_ui instead of the SDK
Some checks failed
Analyze / analyze (push) Has been cancelled
Format / format (push) Has been cancelled
Tests / test (push) Has been cancelled
Flutter 3.47 moved Material and Cupertino out of the SDK into material_ui and cupertino_ui, which ship weekly. The SDK imports are deprecated from the November 2026 stable release and removed in 2027, and the strict pre-push check would block every push then. The app's one Material import now comes from material_ui ^1.5.0, so everything built from here on uses the new import.

Packages that still import package:flutter/material.dart (Serverpod's Flutter packages, later the rich-text editor) see the app's theme and localizations only through MaterialUiCompatibilityBridge, set in MaterialApp.builder. The bridge is deprecated on purpose, as a reminder to remove it, so its use carries a documented ignore until those packages have moved.

google_fonts is removed: it was unused, and by default it downloads fonts from Google at runtime, which sends every user's IP address to Google.

AGENTS.md: Material comes from material_ui.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-29 23:11:00 +02:00
41e968c53e
chore(lint): LeanCode's strict rules and a pre-push check
Some checks failed
Analyze / analyze (push) Has been cancelled
Format / format (push) Has been cancelled
Tests / test (push) Has been cancelled
The workspace root's analysis_options.yaml includes leancode_lint 27 and enables its analyzer plugin (rules for blocs, Equatable and Flutter layout); the server and the app include that file, while the generated client keeps its own options. Plugins can only be enabled at the root of a pub workspace and only reach packages whose options include the root file, which was verified before settling on this layout. Most rules are warnings, casts, inference and raw types are strict, and the check treats infos as fatal too. lints and flutter_lints are no longer needed.

tool/check.sh checks formatting, runs dart analyze --fatal-infos and the server tests; .git/hooks/pre-push links to it, so every push has to pass it. AGENTS.md describes the checklist and how to install the hook in a fresh clone.

Fixes for the new rules: package imports, run() returns Future<void>, the server setup as one cascade, a primary constructor for the app widget, a const and a redundant argument. The workspace root keeps its conventional name `_` with a documented ignore.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-29 23:06:29 +02:00
549406b154
docs(adr): 0002 no end-to-end encryption
Some checks failed
Analyze / analyze (push) Has been cancelled
Format / format (push) Has been cancelled
Tests / test (push) Has been cancelled
Private and shared content is stored in plaintext on the instance and is readable by its operator, as on Mastodon. Private sharing happens only between persons of the same instance; only public content travels between instances. The key management that encryption needed (master key, recovery phrase, per-space keys, re-wrapping, compaction on devices only, signed operations) was the largest subsystem on the plan, and it shut the server out of grammar checking, search and publishing. Whoever trusts no operator can run an instance.

Rules: the privacy page and a notice when sharing say so; deleting content first blanks the payloads of its revisions, because the sync engine keeps rows until their space is deleted; content stays in the versioned payload, because every migration of a synced table locks older app versions out of syncing; server features decode payloads into server-only tables; reports and suggestions go through endpoints, so the author comes from the session. keyId and nonce stay nullable as the one way back.

ADR 0001 gets an "Amended by" note; its decision and rules stand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-29 22:19:08 +02:00
af3a01907e
feat(deploy): Docker Compose stack for the instance
Some checks failed
Analyze / analyze (push) Has been cancelled
Format / format (push) Has been cancelled
Tests / test (push) Has been cancelled
Caddy, the Serverpod server and PostgreSQL 16 in deploy/. Only Caddy publishes ports; the server and Postgres are reachable only inside the Compose network (Docker bypasses ufw, and the server listens on every interface). Secrets come from deploy/.env as environment variables; there is no production passwords.yaml, and .dockerignore keeps local secrets out of the build context.

The server image builds on Serverpod's template with an Ubuntu 24.04 runtime: complete glibc incl. libgcc_s for the SQLite libraries Serverpod 4 bundles, CA certificates, a non-root user, and exec so SIGTERM reaches the server. The scaffold's dev-only docker-compose.yaml is removed.

Verified locally: image builds, all native libraries resolve, no passwords.yaml in the image, migrations apply at start, Caddy serves 200, port 8080 unreachable from the host, Postgres in UTC.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-27 17:18:31 +02:00
2bb8439293
chore(config): production for learn.halkyon.eu, drop staging
apiServer points at learn.halkyon.eu (TLS terminated by Caddy). Production runs neither Insights nor the web server: without their blocks Serverpod doesn't start them. staging.yaml is removed; there is no staging instance.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-27 15:58:44 +02:00
d9adaa7140
docs: AGENTS.md, the agent implements and the developer decides
Every decision goes to the developer; each new pattern is walked through once, similar cases after that are implemented directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-27 15:58:44 +02:00
3487eaf222
docs: ADR 0001, adopt serverpod_offline_sync
Private and shared data sync through serverpod_offline_sync (0.0.8 on Serverpod 4.0.2), with the nine rules the spike established, the consequences, risks and the way out. Evidence: branch spike/offline-sync.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-27 15:58:37 +02:00
ed8f32466f
docs: describe the app, architecture and testing rules in AGENTS.md
Some checks failed
Analyze / analyze (push) Has been cancelled
Format / format (push) Has been cancelled
Tests / test (push) Has been cancelled
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-24 15:32:35 +02:00
75ef1cdb2f
chore: drop unused serverpod_cloud_storage
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-24 15:32:34 +02:00
79c539c219
chore: disable persistent session logs, store files in the database
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-24 15:32:33 +02:00
86b742f510
chore: remove email sign-in, use server-side sessions
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-24 15:32:32 +02:00
b1fe836ed0
chore: bump Serverpod to 4.0.2
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-24 15:32:31 +02:00
059f33ef80
chore: remove the greetings demo
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-24 15:32:31 +02:00
a4fcd98e4a
chore: set app ID to app.halkyon.learn and titles to 'Halkyon Learn'
Furthermore, sets the copyright holder on Windows and macOS.

Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-24 15:32:30 +02:00
10e0cb9117
chore: move to global snap Flutter
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-24 15:32:29 +02:00
e17d99fa51
chore: scaffold the Serverpod 4 build
Deviations from a stock `serverpod create`:
- Dropped Flutter web support, for two reasons:
  - Appflowy editor had issues in the past, potentially related to the
    Flutter-Web IME bridge. Upstream has also open bugs in relation to
that:
    - AppFlowy-IO/appflowy-editor#1029 [Bug][Web] Unwanted space on click
       and overall space bugs (open)
    - AppFlowy-IO/appflowy-editor#782 [Bug] Editor auto-scrolling when
       pressing space too quickly if placed inside a scrollable (open)
  - Offline-first is a required feature. serverpod_offline_sync's SQLite
    support in browsers, maybe via sqlite3.wasm + OPFS, is not
documented.
- SDK constraints raised to ^3.13.0, instead of ^3.12.2, so enjoy the
  newest language features.
- Pinned to Flutter 3.47.4 via FVM.

Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-24 15:32:29 +02:00