Skip to content

Remove tenant and sync wording shown to free users in Database settings #3324

Closed

Description

@mstomar125

Summary

Settings → Database shows cloud-tenant wording to every free user:

  • an explainer paragraph: "A database is a local store on this machine — not a tenant. Each database can sync to one cloud tenant (its workspace) or stay local-only. Opening a database also switches which tenant syncs.";
  • a "Local only · not synced" badge on every database row.

This issue replaces the paragraph with neutral local-database copy and drops the "Local only · not synced" branch.

The "Syncs to tenant · …" badge renders only for a database that a Pro build bound to a tenant. It stays until #3326.

Context

  • ADR-081 (proposed) says core ships no Pro wording. ADR-082 §2.2 (proposed) names this paragraph's tenant sentences as Pro wording that leaves core. If the Pro app wants that explanation, it renders it in its own database.actions or database.row contribution.
  • This PR removes wording, not a Pro feature, so it does not wait for sync. It lowers the Pro-marker ratchet.
  • In the free app no database is ever bound: DatabaseInfo.boundTenantSchema is always null, so the {:else} branch renders on every row.
  • The Pro app gets its row decoration back from Add settings-section and database settings-slot extension points #3312's database.row slot once sync's replacement lands (Delete the Add synced database dialog and tenant badge from Database settings #3326's SYNC gate). Until then, and while the Pro GUI still builds from core HEAD, Pro users lose the explainer and the "Local only · not synced" label on unbound databases. Bound databases keep "Syncs to tenant · X".
  • Add settings-section and database settings-slot extension points #3312 may land before or after this PR. It adds a database.row outlet right after the badge block and leaves the badge alone. If it landed first, leave its outlet where it is.

Scope

packages/desktop-app/src/lib/components/settings/sections/database-settings.svelte (line numbers at af8ddb6):

  • The explainer paragraph: the <p class="text-muted-foreground mb-6 text-sm leading-relaxed"> under the "Databases" header (117-122). Replace its content.
  • The per-row badge block: the <div class="mt-1.5 text-xs"> that holds {#if db.boundTenantSchema} … {:else} … Local only · not synced … {/if} (160-171). Keep only the bound case, and render the wrapper only when db.boundTenantSchema is set.

packages/desktop-app/src/tests/components/settings/database-settings.test.ts (1-78): add one test and keep the three existing ones.

scripts/check-pro-boundary.ts: lower BASELINES.

Out of scope

Steps

  1. Startup sequence (CLAUDE.md):
    • On the primary checkout: git status, then git fetch origin && git pull origin main.
    • Create the worktree: EnterWorktree({name: "issue-<N>-db-settings-tenant-copy"}).
    • Inside it: bun install, then bun run test for the baseline, then bun run gh:comment <N> "Frontend: X passed". Self-assign with bun run gh:assign <N> "@me", then bun run gh:status <N> "In Progress".
  2. Replace the paragraph. Keep the <p> element and its classes so the spacing is unchanged, and replace its body (af8ddb6: 118-121).
    • Suggested copy: A <span class="text-foreground font-medium">database</span> is a separate local store on this machine. Opening one switches the app to it.
    • The new copy must not contain "tenant", "sync", "cloud" or "workspace".
  3. Replace the badge block with:
    {#if db.boundTenantSchema}
      <div class="mt-1.5 text-xs">
        <span class="text-primary bg-primary/10 rounded px-1.5 py-0.5 font-medium">
          Syncs to tenant · {tenantLabel(db.boundTenantSchema)}
        </span>
        <span class="text-muted-foreground/60 ml-1 font-mono">{db.boundTenantSchema}</span>
      </div>
    {/if}
  4. Add the test described under Tests.
  5. Lower the ratchet. Run bun run scripts/check-pro-boundary.ts.
    • It fails with "lower BASELINES.tenantWording" and prints a BASELINES block. Paste that block into scripts/check-pro-boundary.ts.
    • Expect tenantWording to drop by 3, one for each explainer line that says "tenant", and no other marker to move.
    • bun run test:changed does not run the scripts tier for a frontend-only diff, so run the checker by hand.
  6. Finish:
    • bun run test:changed.
    • bun run quality:fix, then commit.
    • git push origin HEAD:issue-<N>-db-settings-tenant-copy. The push runs lint only.
    • gh pr create --repo NodeSpaceAI/nodespace-core --base main --head issue-<N>-db-settings-tenant-copy, then bun run gh:status <N> "In Review".
    • Run /pragmatic-code-review, then /address-review.
    • Merge only after the user approves, with bun run merge <PR#> running in the background. Then ExitWorktree({action: "remove", discard_changes: true}).

Standards:

  • No GitHub issue numbers in code comments.
  • Use createLogger, never console.*.
  • Use bun run test, never bun test.
  • No lint suppression.

Acceptance criteria

  • With an unbound database, Settings → Database shows no "tenant", "not synced" or "Local only" text, and no empty badge wrapper under the status line.
  • In the diff, the bound branch's markup ("Syncs to tenant · {tenantLabel(…)}" plus the raw schema name) is unchanged apart from moving inside the {#if}.
  • The explainer keeps its element, classes and position. Its copy contains none of "tenant", "sync", "cloud" or "workspace".
  • The three existing "Add synced database…" tests pass unchanged.
  • bun run scripts/check-pro-boundary.ts exits 0, BASELINES is lowered in this PR, and no marker count rose.
  • bun run quality:fix is clean and bun run test:changed passes.

Tests and verification

Add this test to database-settings.test.ts. The file mocks no Tauri bridge, so databaseStore.load() produces the implicit "Default" database with boundTenantSchema: null.

  • it('describes databases in neutral, local-only terms'): render DatabaseSettings, await findByText('Default'), then:
    // Built from fragments so this absence check adds no line to the boundary ratchet.
    const removedWording = new RegExp([['ten', 'ant'].join(''), 'not synced', 'local only'].join('|'), 'i');
    expect(container.textContent).not.toMatch(removedWording);
    This follows Add the Pro-boundary ratchet check and the CLAUDE.md Pro/sync placement rule #3299's absence-test convention: a test that asserts a marker is absent builds its needle from fragments, so it adds nothing to the ratchet. Keep the test title free of marker words too.
  • No test for the bound badge. Its fixture would need boundTenantSchema: 'tenant_…', which adds cloudBindState and tenantWording lines, and Delete the Add synced database dialog and tenant badge from Database settings #3326 deletes the badge anyway. Check the bound branch by reviewing the diff.
  • Mutation check. Restore the {:else} branch and confirm the new test fails. Separately, restore the old paragraph and confirm the test fails.

Commands:

bun run --cwd packages/desktop-app test src/tests/components/settings/database-settings.test.ts
bun run scripts/check-pro-boundary.ts
bun run test:changed
bun run quality:fix

Manual check: run bun run dev:browser, open Settings → Database, and confirm that the new copy shows and the "Default" row has no badge.

Dependencies

Risks and rollback


Plan key: C5.1 (pro-boundary DAG).

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

Labels

pro-boundaryPro/core boundary: Pro code moves to nodespace-sync (ADR-081..085)

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions