Skip to content

Feat/open source i18n gdpr - #2

Merged
Aimarmndz merged 14 commits into
mainfrom
feat/open-source-i18n-gdpr
Oct 14, 2026
Merged

Aimarmndz merged 14 commits into
mainfrom
feat/open-source-i18n-gdpr

Conversation

@Aimarmndz

Copy link
Copy Markdown
Owner

No description provided.

WHAT CHANGES
- LICENSE: the official GNU AGPL-3.0 text (from gnu.org, untouched) plus
  additional terms under section 7(b): "Created by Aimar
  (github.com/Aimarmndz)" must be kept in the footer of the public pages
  and in the "About" section of the settings.
- package.json declares AGPL-3.0-or-later.
- CI no longer forbids mentioning the AGPL: it checks that LICENSE and
  package.json agree, that the attribution term is still there and that no
  traces of the proprietary license remain outside the history.
- Contributing: inbound = outbound with the DCO (sign-off), no assignment
  of rights.
- SECURITY.md points to GitHub private vulnerability reporting.
- ADRs 0005 and 0016 become historical; the decision is in
  docs/DECISIONES.md.

VERIFIED
pnpm lint, pnpm typecheck, pnpm test (224) and the CI "Check license" step
locally.

PENDING
The footer with the attribution and the source code link come in later
commits of this branch.
The ITF FFL 2.0 license of Satoshi and Cabinet Grotesk forbids
redistributing the files in a public repository or server, which is
incompatible with publishing the code under the AGPL. They become Bricolage
Grotesque (headings) and Figtree (interface), both SIL OFL 1.1, loaded with
next/font/google like Geist Mono: they are served by the app itself and the
CSP does not change. app/fonts is removed.

VERIFIED
pnpm typecheck, pnpm lint, pnpm test (224) and /login in dev with the
variables of both new fonts.

PITFALL
The old .woff2 files are still in the git history; removing them requires
rewriting it (noted in docs/DECISIONES.md).
WHAT CHANGES
- Optional open sign-up per instance (/register), closed by default. The
  admin opens it in Admin › Instance, and only once the data controller and
  the contact email are set. Consent through a required checkbox
  (User.termsAcceptedAt) and a first information layer next to the form.
- Anti-abuse without third parties: honeypot field, 5 sign-ups/h per IP
  (with a trusted proxy) and 30/h per instance. A concurrent sign-up with
  the same email no longer returns a 500.
- Operator legal details in InstanceConfig and public pages under /legal:
  they describe what the code does, and anything missing shows as "not
  provided".
- POST /api/cron/maintenance deletes the audit log
  (ORGTABLE_AUDIT_RETENTION_DAYS, 90 by default), ended sessions (30 days)
  and notifications (180 days). Cron authorization shared in
  app/lib/api/cron.ts.
- Public footer with legal links, source code (ORGTABLE_SOURCE_URL) and the
  LICENSE attribution on sign-in, sign-up, setup and the legal pages.
- Unified administration tabs (Users, Instance, Audit).
- Fixes the repository URL in install.sh and the docs (Aimarmndz).
- Migration 20261014171630_registration_and_legal (new columns only).

VERIFIED
lint, typecheck, pnpm test, full integration suite (241, including
registration.int.test.ts and maintenance.int.test.ts), pnpm build, compose
variable check and visual review at 375 and 1280 px, light and dark.

PENDING
The legal texts should be reviewed by a professional before opening the
public instance. The maintenance cron has to be scheduled.
…ccount

WHAT CHANGES
/settings gets side navigation (a scrollable row on mobile), with the design
tried first on a design canvas, and these sections:
- Profile: name and email; changing the email asks for the current password.
- Password and sessions: changing it signs out the other sessions; list of
  sessions with a readable browser name, sign out one or all the others.
- API tokens (as before) and Appearance (light, dark or system).
- Privacy and data: JSON download of the personal data
  (/api/account/export, session only) and account deletion with the
  password: own boards with their files, cascade for the rest and cleanup of
  the audit detail. The last ADMIN account cannot be deleted (FOR UPDATE
  lock against simultaneous deletions).
- About: version, source code, license and attribution.

VERIFIED
lint, typecheck, test/user-agent.test.ts and
test/integration/account.int.test.ts (profile, password, sessions, export,
deletion with attachments, last admin and two admins at once). Visual
review at 375 and 1280 px, light and dark.
- The top bar groups settings, privacy, administration and sign out in a
  menu under the initials (native popover, no custom JS). On mobile the
  instance name now fits.
- The tiles on /boards show how many cards they have and, when shared, who
  is in them (with text for screen readers). New query
  getBoardSummariesForUser: the public API does not change.
- Import from JSON is folded under "Create board".

VERIFIED
lint, typecheck, pnpm test (236, including test/initials.test.ts), build
and screenshots at 375 and 1280 px with the menu open, no horizontal
scroll.
- README with a header, main GIF (drag and open a card), gallery (real
  time, card details, calendar, boards, settings, dark and mobile),
  features, privacy, contributing and credits, keeping the required
  structure (requirements, install, commands, variables and deployment).
  A shorter README.en.md in English.
- WebP screenshots and GIFs in docs/screenshots, recorded with the real app
  and fictitious data (@example.com). Scripts to regenerate them in
  scripts/readme-media.
- Docs brought up to date: scheduled tasks (operations), new variables
  (installation), sign-up and own account (authentication), administration
  tabs (admin), opening the instance to the public (self-hosting), roadmap,
  index, new Server Actions, DESIGN.md and CLAUDE.md.

VERIFIED
Relative links and anchors of the changed documents checked with a script
(0 broken). The capture scripts were run end to end from the repo.

PENDING
The README keeps a TODO for the URL of the official public instance.
- app/icon.svg with the brand "o"; the favicon and the Next template SVGs
  (Next and Vercel logos), which were unused, are removed.
- app/robots.ts: with sign-up closed, Disallow: / (a private instance is
  not indexed); with it open, only /login, /register and /legal/.
  /robots.txt is public in proxy.ts.
- Basic Open Graph in the root layout.

VERIFIED
lint, typecheck, pnpm test and registration.int.test.ts with the robots
test.
First CHANGELOG.md (Keep a Changelog) with the work of this branch and a
summary of everything before it.
pnpm audit --prod --audit-level high failed on three advisories published
after the last review (and would fail on main too):

- GHSA-cjq9-62q9-8jv4: SSRF in Next image optimization (next < 16.3.8)
- GHSA-wq5f-xc86-pv6w: sharp < 0.35.5, via next
- GHSA-68fv-2mgg-jv7q: source-map-js < 1.2.2, via postcss

next and eslint-config-next go to 16.3.8 (patch). Two overrides in
pnpm-workspace.yaml force the patched transitive versions, which the
lockfile otherwise kept.

VERIFIED
pnpm audit (only the documented ignored advisory left), shellcheck (via
Docker), lint, typecheck, unit tests and build.
Translations live in locales/<code>/<area>.json, English being the
reference and the fallback for missing messages. Adding a language is
copying en/, translating it and adding one line to locales/index.ts
(guide in locales/README.md).

- app/i18n: language negotiation (cookie, then Accept-Language, then
  English), getI18n() for the server, I18nProvider/useI18n() for the
  client, fmt/plural/messageAt helpers and rich() for <tag> markup.
- User.locale (migration user_locale): restored into the cookie on sign
  in, saved on sign up, used for notifications.
- Language picker (no JS needed) and setLocale action.
- Root layout: <html lang> and metadata follow the language.
- formatDate/formatDateTime take the reader's Intl tag.
- test/i18n.test.ts checks every language against English: same keys,
  placeholders, tags and the plural forms its grammar needs.

The areas are still empty: the interface text moves into them next.

VERIFIED
typecheck (app), test/i18n.test.ts and test/format-date.test.ts.
…nglish

Comments and operator-facing messages of the shell scripts (backup, restore,
update, install, entrypoint), Dockerfile, compose, CI, Prisma schema, Next
and Vitest configs and test stubs are now English. Behaviour, exit codes and
CI commands are unchanged.

The README media scripts seed the demo with English data and capture with an
English browser locale.

test/ops-scripts.test.ts asserts the new English messages (positive and
not.toContain checks).

The decision is recorded in docs/DECISIONES.md ("Bilingual interface" and
"English routes, anchors and parameters; repository fully in English").

VERIFIED
shellcheck (Docker), test/ops-scripts.test.ts (20), prisma validate, docker
compose config and eslint, on this commit in isolation.
Every visible text moves to locales/{en,es}/*.json: sign in, sign up,
setup, legal pages, footer, top bar and account menu, notifications bell,
boards, lists, cards, card modal, filters, calendar, members, settings,
administration, search, server action errors and validation (zod schemas
now carry message keys). English is the default; Spanish is complete.

- Notifications are written in the recipient's language (User.locale).
- Dates, months, relative times and plurals use Intl in the reader's
  language; no hard-coded "es-ES" is left.
- Public REST API messages are English only.
- Language picker in the public footer and in Settings › Appearance.
- Routes, anchors and parameters in English: /legal/privacy|terms|
  cookies|notice, /settings#profile|security|api|appearance|data|about,
  /login?account=deleted. The locale cookie is written by one helper
  (app/i18n/cookie.ts) with the same flags everywhere.
- "Created by" in Settings › About uses the same message as the footer.
- Code comments and all tests are in English. New integration tests
  cover the request language, the cookie, the account preference and
  per-recipient notifications (test/integration/locale.int.test.ts).

VERIFIED
lint, typecheck, unit tests (258), integration tests (266) and build, on
this commit in isolation; visual check of 13 pages in English and Spanish
at 375 and 1280 px (no overflow, no console errors, no leftover
placeholders, correct <html lang>).
- README.md is now the English README (merged with the old README.en.md
  draft); README.es.md is its full Spanish version. Both mention the
  bilingual interface and link the translation guide (locales/README.md).
- Every document under docs/, plus CHANGELOG, SECURITY, DESIGN, PRODUCT,
  CLAUDE.md and scripts/readme-media/README.md, is in English and up to
  date with the code (routes, settings anchors, env vars, i18n).
- docs/roadmap.md becomes a public roadmap (Shipped / Planned / Ideas /
  Smaller improvements) without internal milestone numbering.
- docs/contributing.md: translations section and English-only convention.
- docs/DECISIONES.md and the ADRs in docs/decisions/ translated (79
  entries kept, same dates and order), plus the decision on English
  routes and anchors.
- docs/screenshots: GIFs and WebP captures retaken with the English
  interface and English demo data.

VERIFIED
Link and anchor check over every Markdown file (0 broken).
@Aimarmndz
Aimarmndz merged commit bf9e162 into main Oct 14, 2026
1 check passed
@Aimarmndz
Aimarmndz deleted the feat/open-source-i18n-gdpr branch October 20, 2026 11:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant