Skip to content

Wire up template-based project creation via JSON snapshot import#2281

Open
myieye wants to merge 6 commits into
developfrom
claude/investigate-issue-1920-f6yHG
Open

Wire up template-based project creation via JSON snapshot import#2281
myieye wants to merge 6 commits into
developfrom
claude/investigate-issue-1920-f6yHG

Conversation

@myieye

@myieye myieye commented May 20, 2026

Copy link
Copy Markdown
Collaborator

This feature is still dev-only, because it's a dead-end and we don't want to sell it as being more than that. The "Create example project" is what we still expose to our users, because it's so explicitly a demo feature. But it now also uses the template, so it gets the canonical morph-types, sem-doms, PoS etc.

image image image

@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 8318992c-fca7-4839-b08e-3055dd1271ae

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR implements end-to-end template-based project creation, allowing users to create blank projects with custom codes and vernacular writing systems. It adds a SQL template resource with GUID hydration and hash-chain rebuild logic, backend APIs for template-based creation, frontend UI flows, comprehensive test infrastructure, and localization updates.

Changes

Template-based project creation

Layer / File(s) Summary
Template resource loading and application
backend/FwLite/LcmCrdt/Project/ProjectTemplate.cs, backend/FwLite/LcmCrdt/LcmCrdt.csproj
ProjectTemplate static class loads the embedded SQL template, hydrates Guid_N tokens to deterministic fresh GUIDs per token, substitutes vernacular abbreviations and morph-types seed commit placeholders, applies SQL to SQLite, and fabricates a synthetic commit to force hash-chain rebuild via DataModel.AddRangeFromSync.
CRDT template-based project creation
backend/FwLite/LcmCrdt/CrdtProjectsService.cs
CreateProjectFromTemplate method validates project code and requires VernacularWs, creates a new SQLite database, applies the embedded template via ProjectTemplate, overwrites the template's ProjectData row with caller-provided identity and metadata, refreshes project state, forces hash-chain rebuild, and handles cleanup on failure. CreateProjectRequest extended with optional VernacularWs field.
HTTP project creation endpoints
backend/FwLite/FwLiteWeb/Routes/ProjectRoutes.cs
/api/project POST endpoint now requires name, code, and vernacularWs parameters and delegates to CreateProjectFromTemplate with manager role; /api/project/demo POST endpoint validates name and creates example projects; new ValidateProjectCode helper centralizes project-code validation rules.
Unified service layer
backend/FwLite/FwLiteShared/Projects/CombinedProjectsService.cs
CreateProject method signature changed to accept name, code, and vernacularWs; now creates projects from template instead of example projects. New CreateDemoProject(name) method for example-project creation. Both JS-invokable.
Frontend API client
frontend/viewer/src/lib/services/projects-service.ts, frontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/Projects/ICombinedProjectsService.ts
createProject(name, code, vernacularWs) method validates inputs and POSTs to /api/project; new createDemoProject(name) method POSTs to /api/project/demo; private postOk helper centralizes POST error handling. ICombinedProjectsService interface updated to match new signatures.
Frontend project creation UI
frontend/viewer/src/home/HomeView.svelte
Demo-project creation flow replaces example-project logic via createDemoProject(). New dev-gated "Create Blank Project" section introduces UI inputs for project name, project code (defaults to name), and vernacular writing system, wired to createNewProject() flow.
Template test infrastructure
backend/FwLite/FwLiteProjectSync.Tests/ProjectTemplateTests.cs, backend/FwLite/FwLiteProjectSync.Tests/SqliteDump.cs, backend/FwLite/FwLiteProjectSync.Tests/TemplateGuidScrubbing.cs
ProjectTemplateTests provides test lifecycle and methods for regenerating template.sql from a source FwDataProject and validating template application; SqliteDump utility shells out to sqlite3 CLI to dump databases; TemplateGuidScrubbing helper sanitizes SQL by replacing instance GUIDs with stable tokens while preserving canonical entity GUIDs.
Template-created project validation test
backend/FwLite/LcmCrdt.Tests/OpenProjectTests.cs
Integration test CreateProjectFromTemplateAppliesRequestedIdentity creates a project from template with random code, validates project identity fields and expected morph/writing system data, then cleans up the database.
Supporting changes
backend/FwLite/LcmCrdt/CurrentProjectService.cs, backend/FwLite/LcmCrdt/Objects/PreDefinedData.cs, backend/FwLite/LcmCrdt/LcmCrdt.csproj, frontend/viewer/src/locales/*.po, frontend/viewer/src/project/demo/in-memory-demo-api.ts
CurrentProjectService safely handles missing ProjectData during migration via nullable FirstOrDefaultAsync; csproj grants internal visibility to test assembly and embeds template.sql resource; all locale files receive new translation keys for blank-project UI strings; in-memory-demo-api stubs updated for new method signatures.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • sillsdev/languageforge-lexbox#1531: Updates CrdtProjectsService.CreateProjectRequest to use project codes instead of names; directly related to the identifier-model changes underlying this PR's template creation API.
  • sillsdev/languageforge-lexbox#2278: Modifies per-project morph-types seed commit ID generation strategy, directly connected to how this PR parameterizes the template's seed commit from projectId.
  • sillsdev/languageforge-lexbox#2121: Updates frontend localization resources by adding new UI string entries, with file-level overlap in frontend/viewer/src/locales/ additions.

Suggested reviewers

  • rmunn
  • hahn-kev

🐰 A template blooms, no longer bound,
Fresh projects spring from seed we've found,
Codes and writing systems dance,
Hash chains rebuild at every chance—
Blank projects bloom with code in hand!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.75% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title 'Wire up template-based project creation via JSON snapshot import' directly summarizes the main change: implementing template-based project creation through snapshot imports.
Description check ✅ Passed The PR description provides clear context about the feature's purpose, implementation approach, and user-facing changes with supporting UI screenshots.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/investigate-issue-1920-f6yHG

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the 💻 FW Lite issues related to the fw lite application, not miniLcm or crdt related label May 20, 2026
@github-actions

github-actions Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

UI unit Tests

  1 files  ±0   62 suites  ±0   29s ⏱️ -3s
186 tests ±0  186 ✅ ±0  0 💤 ±0  0 ❌ ±0 
258 runs  ±0  258 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit 7a38c81. ± Comparison against base commit 16a9173.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

C# Unit Tests

165 tests   165 ✅  19s ⏱️
 23 suites    0 💤
  1 files      0 ❌

Results for commit 7a38c81.

♻️ This comment has been updated with latest results.

@argos-ci

argos-ci Bot commented May 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - Jun 22, 2026, 1:29 PM

Comment thread backend/FwLite/LcmCrdt/Project/ProjectTemplate.cs Fixed
Comment thread backend/FwLite/LcmCrdt/CrdtProjectsService.cs Fixed
@myieye myieye force-pushed the claude/investigate-issue-1920-f6yHG branch from 5d1291f to 5d41a94 Compare May 20, 2026 15:09

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🧹 Nitpick comments (1)
backend/FwLite/FwLiteShared/Projects/CombinedProjectsService.cs (1)

211-225: ⚡ Quick win

Return the CRDT tasks directly instead of wrapping them in Task.Run.

These methods already delegate to async APIs. The extra Task.Run just adds a thread-pool hop and makes cancellation/context flow harder to reason about.

Suggested fix
 [JSInvokable]
- public Task CreateProject(string name, string code, WritingSystemId vernacularWs)
- {
-     return Task.Run(async () =>
-     {
-         await crdtProjectsService.CreateProjectFromTemplate(new(name, code, Role: UserProjectRole.Manager, VernacularWs: vernacularWs));
-     });
- }
+ public Task CreateProject(string name, string code, WritingSystemId vernacularWs) =>
+     crdtProjectsService.CreateProjectFromTemplate(
+         new(name, code, Role: UserProjectRole.Manager, VernacularWs: vernacularWs));

 [JSInvokable]
- public Task CreateDemoProject(string name)
- {
-     return Task.Run(async () =>
-     {
-         await crdtProjectsService.CreateExampleProject(name);
-     });
- }
+ public Task CreateDemoProject(string name) =>
+     crdtProjectsService.CreateExampleProject(name);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/FwLite/FwLiteShared/Projects/CombinedProjectsService.cs` around lines
211 - 225, CreateProject and CreateDemoProject are wrapping already-async
crdtProjectsService calls in Task.Run, causing unnecessary thread-pool hops and
lost context/cancellation; remove the Task.Run wrappers and return the
underlying tasks directly (either by making the methods async and awaiting
crdtProjectsService.CreateProjectFromTemplate(...) and
crdtProjectsService.CreateExampleProject(...), or by returning those
Task-returning calls directly) while keeping the [JSInvokable] attribute on
CreateDemoProject and preserving the parameter types (name, code, vernacularWs)
and role construction used with CreateProjectFromTemplate.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/FwLite/FwLiteWeb/Routes/ProjectRoutes.cs`:
- Around line 84-89: The ValidateProjectCode method performs ProjectExists(code)
before enforcing the project code regex, which can allow malformed/path-like
input to reach storage; reorder the checks in ValidateProjectCode so the format
validation using CrdtProjectsService.ProjectCode().IsMatch(code) runs
immediately after the null/whitespace check and before calling
projectService.ProjectExists(code), returning the existing "Only letters,
numbers, '-' and '_' are allowed" BadRequest when the regex fails; keep the
other checks and return values unchanged.

In `@backend/FwLite/LcmCrdt/CrdtProjectsService.cs`:
- Around line 197-212: The current OverwriteProjectDataRow performs an
unfiltered ExecuteUpdateAsync on dbContext.ProjectData which can overwrite every
row; add a fail-fast guard that restricts the update to the intended row and
verifies existence before mutating: first query (e.g., using Any/Count or
FirstOrDefault) to ensure a single ProjectData with the given data.Id exists
(throw if not exactly one), then call ExecuteUpdateAsync on
dbContext.ProjectData with a Where filter for p => p.Id == data.Id so only that
row is updated; reference the OverwriteProjectDataRow method, the ProjectData
DbSet, and the ExecuteUpdateAsync call when making these changes.
- Around line 158-183: The template creation flow calls
CurrentProjectService.SetupProjectContextForNewDb(crdtProject) but then awaits
RefreshProjectData() without assigning its return value, leaving
crdtProject.Data null before invoking request.AfterCreate; change the code to
assign the result of currentProjectService.RefreshProjectData() to
crdtProject.Data (i.e., crdtProject.Data = await
currentProjectService.RefreshProjectData()) so downstream callers like
request.AfterCreate receive the initialized ProjectData.

In `@backend/FwLite/LcmCrdt/CurrentProjectService.cs`:
- Around line 116-118: The current logic in CurrentProjectService that checks
projectData (variable projectData) and then skips morph-type seeding if
projectData is null causes a permanent skip while the one-time migration cache
is set; change the flow so that a null ProjectData does not mark the
migration/seed as completed and does not block future attempts: ensure you only
compute PreDefinedData.MorphTypesSeedCommitId(projectData.Id) and run the Commit
existence check when projectData != null, but do not set the migration cache or
mark seeding as done when projectData is null—instead leave the cache unset (or
schedule a retry) so morph-type seeding (the Commit/seed path) will be retried
once ProjectData becomes available; update the code around
dbContext.ProjectData, PreDefinedData.MorphTypesSeedCommitId, Commit and the
migration cache logic to implement this behavior.

In `@backend/FwLite/LcmCrdt/Project/ProjectTemplate.cs`:
- Around line 48-60: The template replacement injects request-derived strings
(vernacularWs.Code and the AbbreviationFor(...) fallback) directly into
resolvedSql via Replace, which can break or inject SQL; before calling
HydrateGuids(...).Replace(...) validate or strictly whitelist the writing-system
values used for VernacularWsPlaceholder and VernacularNamePlaceholder and the
AbbreviationFor(...) result (e.g., allow only a tight regex like
alphanumeric/underscore/hyphen) and reject the request if they don't match, or
alternatively escape them safely for SQL string literals; ensure this validation
is applied to vernacularWs.Code and the value returned by
AbbreviationFor(vernacularWs) and only then build cmd.CommandText (resolvedSql +
"\nPRAGMA writable_schema=RESET;") so no unvalidated user data can break
templateSql or targetSqlitePath usage.

In `@frontend/viewer/src/home/HomeView.svelte`:
- Around line 79-81: Trim the user-provided inputs (customNewProjectName and
customNewProjectCode) before deciding whether to use them or fall back to
defaults: compute trimmedName = customNewProjectName?.trim() and trimmedCode =
customNewProjectCode?.trim(), then use trimmedName ||
`blank-dev-${dateTimeProjectSuffix()}` for projectName and trimmedCode ||
projectName for projectCode, and pass those values into
projectsService.createProject to prevent whitespace-only values from being
treated as valid.

In `@frontend/viewer/src/lib/services/projects-service.ts`:
- Around line 30-40: The current input validation in createProject and
createDemoProject (methods in projects-service.ts) uses falsy checks (if
(!name), if (!code), if (!vernacularWs)) which permit whitespace-only strings;
update both createProject and createDemoProject to trim inputs first and reject
when trimmed values are empty (e.g., const trimmedName = name.trim(); if
(!trimmedName) throw ...), and use the trimmed values when building the request
URL so whitespace-only values are rejected client-side before sending to the
backend.

In `@frontend/viewer/src/locales/ko.po`:
- Around line 435-438: Add Korean translations for the newly introduced
blank-project strings by filling the empty msgstr entries in
frontend/viewer/src/locales/ko.po: provide a localized Korean string for the
msgid "Create Blank Project" and do the same for the two other new msgid entries
added in the same blank-project flow (the entries noted at the ranges around
lines 1466-1469 and 2025-2028), ensuring each msgstr contains the correct Korean
translation and preserves any punctuation/formatting from the msgid.

In `@frontend/viewer/src/locales/ms.po`:
- Around line 435-438: Fill in the missing Malay translations for the new
blank-project message keys in frontend/viewer/src/locales/ms.po: set msgstr for
the shown msgid "Create Blank Project" and the two other blank msgid/msgstr
pairs referenced at ranges 1466-1469 and 2025-2028; update each msgstr with the
correct Malay translation (ensure UTF-8 encoding and preserve the original msgid
lines and PO file formatting).

In `@frontend/viewer/src/locales/sw.po`:
- Around line 435-438: The PO entries for the new project-creation strings
(e.g., msgid "Create Blank Project" in viewer/src/locales/sw.po and the other
untranslated entries at the ranges you noted) are missing Swahili translations;
open viewer/src/locales/sw.po, locate each untranslated msgid (like "Create
Blank Project") and fill in the corresponding msgstr with an accurate Swahili
translation, making sure none remain empty and preserving plural/context markers
and file references; after updating, run your i18n validation/compile step to
ensure the PO file is syntactically valid.

In `@frontend/viewer/src/locales/vi.po`:
- Around line 435-438: Several new Vietnamese translations are missing: locate
the msgid entries such as "Create Blank Project" (and the other empty msgstr
blocks noted around the other ranges) in frontend/viewer/src/locales/vi.po and
provide appropriate Vietnamese translations by filling each msgstr with the
correct Vietnamese text (e.g., a natural translation for "Create Blank Project")
for all empty entries referenced (including the blocks at the other mentioned
ranges) so the new blank-project UI displays localized text.

---

Nitpick comments:
In `@backend/FwLite/FwLiteShared/Projects/CombinedProjectsService.cs`:
- Around line 211-225: CreateProject and CreateDemoProject are wrapping
already-async crdtProjectsService calls in Task.Run, causing unnecessary
thread-pool hops and lost context/cancellation; remove the Task.Run wrappers and
return the underlying tasks directly (either by making the methods async and
awaiting crdtProjectsService.CreateProjectFromTemplate(...) and
crdtProjectsService.CreateExampleProject(...), or by returning those
Task-returning calls directly) while keeping the [JSInvokable] attribute on
CreateDemoProject and preserving the parameter types (name, code, vernacularWs)
and role construction used with CreateProjectFromTemplate.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 53d155a9-ef29-4a5b-b169-3e9703e04d6a

📥 Commits

Reviewing files that changed from the base of the PR and between e362dd4 and 5d41a94.

📒 Files selected for processing (25)
  • backend/FwLite/FwLiteProjectSync.Tests/ProjectTemplateTests.ApplyTemplate.verified.txt
  • backend/FwLite/FwLiteProjectSync.Tests/ProjectTemplateTests.cs
  • backend/FwLite/FwLiteProjectSync.Tests/SqliteDump.cs
  • backend/FwLite/FwLiteProjectSync.Tests/TemplateGuidScrubbing.cs
  • backend/FwLite/FwLiteShared/Projects/CombinedProjectsService.cs
  • backend/FwLite/FwLiteWeb/Routes/ProjectRoutes.cs
  • backend/FwLite/LcmCrdt.Tests/OpenProjectTests.cs
  • backend/FwLite/LcmCrdt/CrdtProjectsService.cs
  • backend/FwLite/LcmCrdt/CurrentProjectService.cs
  • backend/FwLite/LcmCrdt/LcmCrdt.csproj
  • backend/FwLite/LcmCrdt/Objects/PreDefinedData.cs
  • backend/FwLite/LcmCrdt/Project/ProjectTemplate.cs
  • backend/FwLite/LcmCrdt/Templates/template.sql
  • frontend/viewer/src/home/HomeView.svelte
  • frontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/Projects/ICombinedProjectsService.ts
  • frontend/viewer/src/lib/services/projects-service.ts
  • frontend/viewer/src/locales/en.po
  • frontend/viewer/src/locales/es.po
  • frontend/viewer/src/locales/fr.po
  • frontend/viewer/src/locales/id.po
  • frontend/viewer/src/locales/ko.po
  • frontend/viewer/src/locales/ms.po
  • frontend/viewer/src/locales/sw.po
  • frontend/viewer/src/locales/vi.po
  • frontend/viewer/src/project/demo/in-memory-demo-api.ts
💤 Files with no reviewable changes (1)
  • backend/FwLite/LcmCrdt/Objects/PreDefinedData.cs

Comment thread backend/FwLite/FwLiteWeb/Routes/ProjectRoutes.cs Outdated
Comment thread backend/FwLite/LcmCrdt/CrdtProjectsService.cs Outdated
Comment thread backend/FwLite/LcmCrdt/CrdtProjectsService.cs Outdated
Comment thread backend/FwLite/LcmCrdt/CurrentProjectService.cs Outdated
Comment thread backend/FwLite/LcmCrdt/Project/ProjectTemplate.cs Outdated
Comment thread frontend/viewer/src/lib/services/projects-service.ts Outdated
Comment thread frontend/viewer/src/locales/ko.po
Comment thread frontend/viewer/src/locales/ms.po
Comment thread frontend/viewer/src/locales/sw.po
Comment thread frontend/viewer/src/locales/vi.po
Comment thread backend/FwLite/LcmCrdt/CrdtProjectsService.cs Fixed
@myieye myieye marked this pull request as draft May 27, 2026 10:58
@github-actions github-actions Bot added the 📦 Lexbox issues related to any server side code, fw-headless included label May 28, 2026
@myieye myieye force-pushed the claude/investigate-issue-1920-f6yHG branch from 636dbe5 to 00c93ac Compare May 29, 2026 06:56
Comment thread backend/FwLite/LcmCrdt/CrdtProjectsService.cs Fixed
@myieye myieye force-pushed the claude/investigate-issue-1920-f6yHG branch 3 times, most recently from c28ad1f to a8efac4 Compare June 1, 2026 15:54
myieye added a commit that referenced this pull request Jun 2, 2026
Comment-only pass on PR #2281:
- Fix a stale claim in CurrentProjectService: after the ReseedProject
  switch, templated projects no longer resolve their morph-types commit
  to MorphTypesSeedCommitId, so the re-seed adds one redundant (harmless)
  commit on first open rather than deduping.
- Drop duplicated rationale (SeedMorphTypes stated 3x → param doc only;
  local-only stated 2x → SyncService.UploadProject only).
- Trim over-long test comments; drop a reference to a renamed test.

Bumps the harmony submodule to b043d87 (CommitBase.cs LF normalization).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

C# FwHeadless Unit Tests

48 tests  ±0   48 ✅ ±0   16s ⏱️ ±0s
 5 suites ±0    0 💤 ±0 
 1 files   ±0    0 ❌ ±0 

Results for commit 7a38c81. ± Comparison against base commit 16a9173.

♻️ This comment has been updated with latest results.

Comment thread backend/FwLite/LcmCrdt/Project/ProjectTemplate.cs Outdated
@myieye myieye changed the title Wire up template-based project creation Wire up template-based project creation via JSON snapshot import Jun 17, 2026
myieye added a commit that referenced this pull request Jun 17, 2026
Comment-only pass on PR #2281:
- Fix a stale claim in CurrentProjectService: after the ReseedProject
  switch, templated projects no longer resolve their morph-types commit
  to MorphTypesSeedCommitId, so the re-seed adds one redundant (harmless)
  commit on first open rather than deduping.
- Drop duplicated rationale (SeedMorphTypes stated 3x → param doc only;
  local-only stated 2x → SyncService.UploadProject only).
- Trim over-long test comments; drop a reference to a renamed test.

Bumps the harmony submodule to b043d87 (CommitBase.cs LF normalization).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@myieye myieye force-pushed the claude/investigate-issue-1920-f6yHG branch 2 times, most recently from 4cafdb7 to bb3fe8e Compare June 18, 2026 13:56
myieye and others added 5 commits June 22, 2026 15:26
Squash of the template-creation feature, rebased onto develop's harmony-NuGet migration.
Imports a persisted ProjectSnapshot (template.json) via the MiniLcm import path; no SQL
template, no ReseedProject.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Revert the server-side CrdtCommits composite (ProjectId, Id) primary-key change
out of this PR — it's unrelated to template-based project creation. The change is
preserved as a git patch (plus a unique-index follow-up) in #2365.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Naming: rename the ApplyTemplate test to VerifyCreateFromTemplate, the embedded
template to blank-project-template.json, and the create endpoints to
/api/project/create and /api/project/create-demo. Regenerate the verified snapshot.

Drop now-redundant seeding: with every create path going through the template,
the SeedMorphTypes flag and the test-only SeedNewProjectData / SeedSystemData path
are dead, along with the predefined parts-of-speech / complex-form-type /
semantic-domain / custom-view seeders and their hard-coded GUIDs. ExampleProjectData
resolves Noun and Compound by name instead. PreDefinedData keeps only the morph-type
seeder still used by the open-time backfill.

Revert unrelated drift back to develop (CurrentProjectService morph-type backfill,
SyncService.UploadProject), drop the in-memory template cache in favour of reading
the embedded snapshot per use, remove two redundant templated-project tests, and fix
stale/backwards comments (create is dev-only and demo is user-facing; the snapshot
serialization keeps a complete record, it isn't required by the sync diff).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Make CreateProjectFromTemplate take vernacular (required) + analysis (optional)
  writing systems as explicit params instead of optional CreateProjectRequest
  properties, so the required one is enforced at compile time.
- Create the requested writing systems by adding them to the loaded template
  snapshot before import (everything created together, in dependency order) rather
  than a post-import CreateWritingSystem call.
- Let callers specify an analysis WS end-to-end (endpoint, JSInvokable, dialog);
  English always ships in the template, the requested one is added if different.
- Restore NewProject_HasAllCanonicalMorphTypes (the open-time backfill keeps it
  green) instead of deleting it; SanitizeProjectCode now throws rather than
  inventing a fallback code.
- New Project button: show "(Local only)" and drop the "Add your own entries" line.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
I shouldn't have dropped the second line — only the first-line "(Local only)"
caveat was requested. Bring back the subtitle as "Create a new FieldWorks Lite
project".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Neutralizes a CWE-117 log-injection finding on the EnsureDeleteProject log
lines. The value is already effectively guarded (project code is regex-
validated, the only path-supplying caller composes a config root + GUID),
so this is defense-in-depth rather than a live vuln.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@myieye myieye force-pushed the claude/investigate-issue-1920-f6yHG branch from 9d52617 to 7a38c81 Compare June 22, 2026 13:26
@myieye myieye marked this pull request as ready for review June 22, 2026 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FW Lite issues related to the fw lite application, not miniLcm or crdt related 📦 Lexbox issues related to any server side code, fw-headless included

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants