From dac2d6a3967b78697957a39c1a828f2266c8eb62 Mon Sep 17 00:00:00 2001 From: helbertm Date: Wed, 27 May 2026 00:21:00 -0300 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20exibir=20hist=C3=B3rico=20acumulado?= =?UTF-8?q?=20de=20novidades=20entre=20vers=C3=B5es=20n=C3=A3o=20vistas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 101 insertions(+), 5 deletions(-) diff --git a/index.html b/index.html index 462fdcb..46508d9 100644 --- a/index.html +++ b/index.html @@ -6668,6 +6668,7 @@

Sem conexão com a internet

"Alertas de novos releases." ] }; + let RELEASE_VERSIONS = ["0.1.1"]; const CURRENT_STORAGE_SCHEMA_VERSION = 2; const SHORTCUT_ACTIONS = { copy: "F6", @@ -7724,6 +7725,22 @@

Sem conexão com a internet

return ``; } + function parseSemver(version) { + const match = String(version || "").trim().match(/^(\d+)\.(\d+)\.(\d+)$/); + if (!match) return null; + return [Number(match[1]), Number(match[2]), Number(match[3])]; + } + + function compareSemver(a, b) { + const pa = parseSemver(a); + const pb = parseSemver(b); + if (!pa || !pb) return String(a).localeCompare(String(b)); + for (let i = 0; i < 3; i++) { + if (pa[i] !== pb[i]) return pa[i] - pb[i]; + } + return 0; + } + function normalizeReleaseNoteForUsers(rawNote) { if (!rawNote) return ""; let note = String(rawNote).trim(); @@ -7780,6 +7797,74 @@

Sem conexão com a internet

return bulletLines.slice(0, 12); } + function parseReleaseHistoryFromChangelog(changelogText) { + if (!changelogText) return { versions: [], notesByVersion: {} }; + + const lines = changelogText.split("\n"); + const sections = []; + let current = null; + + for (const line of lines) { + const headingMatch = line.match(/^##\s+\[?v?(\d+\.\d+\.\d+)\]?/i); + if (headingMatch) { + if (current) sections.push(current); + current = { version: headingMatch[1], lines: [] }; + continue; + } + if (current) current.lines.push(line); + } + if (current) sections.push(current); + + const notesByVersion = {}; + const versions = []; + + sections.forEach((section) => { + const bullets = section.lines + .map(line => line.trim()) + .filter(line => /^[-*]\s+/.test(line)) + .map(line => line.replace(/^[-*]\s+/, "").trim()) + .map(normalizeReleaseNoteForUsers) + .filter(Boolean) + .slice(0, 16); + + if (bullets.length) { + notesByVersion[section.version] = bullets; + versions.push(section.version); + } + }); + + return { versions, notesByVersion }; + } + + function getReleaseVersionsForModal(currentVersion, seenVersion) { + if (!currentVersion) return []; + if (!seenVersion || seenVersion === currentVersion) return [currentVersion]; + + const available = RELEASE_VERSIONS.length ? RELEASE_VERSIONS : [currentVersion]; + const currentIndex = available.indexOf(currentVersion); + if (currentIndex === -1) return [currentVersion]; + + const seenIndex = available.indexOf(seenVersion); + if (seenIndex !== -1) { + if (seenIndex <= currentIndex) return [currentVersion]; + return available.slice(currentIndex, seenIndex); + } + + // Fallback when seen version is not in changelog history loaded on the page. + const filtered = available.filter(v => compareSemver(v, currentVersion) <= 0 && compareSemver(v, seenVersion) > 0); + return filtered.length ? filtered : [currentVersion]; + } + + function buildReleaseNotesHistoryHtml(versions) { + const items = versions.filter(Boolean); + if (!items.length) return buildReleaseNotesList(APP_VERSION); + + return items.map((version) => { + const notes = RELEASE_NOTES[version] || ["Melhorias gerais de estabilidade e usabilidade."]; + return `

v${escapeHtml(version)}

`; + }).join(""); + } + async function loadReleaseMetadataFromRepoFiles() { // Local file:// runs block fetch for sibling files in several browsers; keep static fallback there. if (location.protocol === "file:") return; @@ -7796,9 +7881,13 @@

Sem conexão com a internet

const changelogResponse = await fetch("./CHANGELOG.md", { cache: "no-store" }); if (changelogResponse.ok) { const changelogText = await changelogResponse.text(); - const parsedNotes = parseReleaseNotesFromChangelog(APP_VERSION, changelogText); - if (parsedNotes.length) { - RELEASE_NOTES[APP_VERSION] = parsedNotes; + const history = parseReleaseHistoryFromChangelog(changelogText); + if (history.versions.length) { + RELEASE_VERSIONS = history.versions; + RELEASE_NOTES = { ...RELEASE_NOTES, ...history.notesByVersion }; + } else { + const parsedNotes = parseReleaseNotesFromChangelog(APP_VERSION, changelogText); + if (parsedNotes.length) RELEASE_NOTES[APP_VERSION] = parsedNotes; } } } catch (error) { @@ -7807,11 +7896,18 @@

Sem conexão com a internet

} function openReleaseNotesModal(markAsSeen = true) { + const seenVersion = storage.get(STORAGE_KEYS.LAST_SEEN_RELEASE_VERSION, ""); + const versionsToShow = getReleaseVersionsForModal(APP_VERSION, seenVersion); + if (releaseNotesSummary) { - releaseNotesSummary.textContent = `Seu editor foi atualizado para a versão ${APP_VERSION}.`; + if (!seenVersion || seenVersion === APP_VERSION || versionsToShow.length === 1) { + releaseNotesSummary.textContent = `Seu editor foi atualizado para a versão ${APP_VERSION}.`; + } else { + releaseNotesSummary.textContent = `Seu editor foi atualizado da versão ${seenVersion} para ${APP_VERSION}.`; + } } if (releaseNotesContent) { - releaseNotesContent.innerHTML = buildReleaseNotesList(APP_VERSION); + releaseNotesContent.innerHTML = buildReleaseNotesHistoryHtml(versionsToShow); } modalController.open(releaseNotesModal); if (markAsSeen) markReleaseVersionAsSeen(); From c6df149bbc477a1bab5f5489b6eea9e7afe635c6 Mon Sep 17 00:00:00 2001 From: helbertm Date: Tue, 2 Jun 2026 22:13:16 -0300 Subject: [PATCH 2/8] refactor(ui): align workspace surfaces with design system --- design_system.md | 99 +++++++++++++++ index.html | 324 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 329 insertions(+), 94 deletions(-) create mode 100644 design_system.md diff --git a/design_system.md b/design_system.md new file mode 100644 index 0000000..c288f2d --- /dev/null +++ b/design_system.md @@ -0,0 +1,99 @@ +# hSQLite Editor Design System + +## Objective +Define a consistent UX/UI baseline for a keyboard-first SQLite workspace with a calm productivity profile inspired by GitHub/Resend. + +## Product Modes +- Primary mode: Support/TI operational analysis. +- Secondary mode: Didactic exploration. + +Rule: +- Primary mode actions must always have visual priority over didactic actions. + +## Design Principles +- Keyboard-first for all primary actions. +- Low-noise visuals, clear hierarchy, dense but readable layout. +- Accessibility by default (focus-visible, dialog semantics, ARIA state). +- Responsive behavior with explicit density changes by breakpoint. + +## Typography +- Keep current sans stack for now. +- Use only 4 semantic sizes: `12`, `14`, `16`, `20`. +- Titles and section labels must follow semantic role, not ad hoc sizing. + +## Spacing Scale +- Spacing tokens: `4, 8, 12, 16, 20, 24`. +- Button heights: +- `sm`: 30px +- `md`: 36px (default) +- `lg`: 40px (primary only) + +## Action Hierarchy +- `primary`: single dominant action per context (e.g. Run SQL). +- `secondary`: frequent but non-primary actions. +- `ghost`: supportive actions with low emphasis. +- `destructive`: explicit risk operations only. +- `icon-only`: compact utility actions with tooltip and aria-label. + +## Component Contracts +- Buttons use one primitive matrix: variant (`primary`, `secondary`, `ghost`, `destructive`, `icon-only`) and size (`sm`, `md`, `lg`). +- Button content slots are stable: optional icon/symbol, optional shortcut badge, label. Per-button visual alignment fixes are not allowed unless documented as a component rule. +- Segmented theme/session controls are switches, not action buttons. They require `role="switch"`, `aria-checked`, and visible state. +- Menu triggers implemented with `summary` must match button focus, hover, height, border, and radius behavior. +- SQL tabs follow the accessible tab pattern: tablist, tab roles, roving `tabindex`, ArrowLeft/ArrowRight navigation, Home/End navigation, active-tab scroll-into-view, and overflow affordance only when content exceeds the strip. +- Tab close/rename affordances must remain discoverable on keyboard and touch. Hover may emphasize controls, but must not be the only way to discover the capability. +- Empty states in the primary workflow are operational and low-motion. Didactic personality belongs in optional help/onboarding surfaces. +- Result toolbars must expose labels for compact/icon controls and keep pagination, filtering, sort reset, selection reset, and freeze reset visually distinct but consistent. + +## Motion Policy +- Decorative or ambient animation must never be required to understand or complete a task. +- `prefers-reduced-motion: reduce` disables nonessential animation and transitions. +- Primary workflow feedback may use short motion only when it improves status visibility, such as running-state pulse or toast entry. + +## Keyboard System +- Single source of truth: each shortcut is defined once and rendered from the same map. +- No duplicated keybinding. +- Every shortcut badge must match runtime behavior. +- Provide one keyboard help surface (`?` or `Ctrl/Cmd+K` entry). +- For UX rewrite phase: allow single-letter shortcuts only in modal context, never as global workspace shortcuts. +- Modal shortcut baseline (rewrite backlog): `Enter` confirm, `Esc` cancel/close, `O` confirm, `A` cancel when focus is not in text input fields. + +## Accessibility Rules +- Do not globally suppress focus outline. +- Use `:focus-visible` with high-contrast ring. +- All modals require: `role="dialog"`, `aria-modal="true"`, labelled title, Escape to close, focus trap, focus return. +- Sortable table headers require `aria-sort`. +- Toggle controls require semantic switch state and keyboard support. +- `summary` menu triggers require the same focus-visible treatment as buttons. +- Horizontal tab overflow requires keyboard access and active-item visibility. + +## Layout Rules +- Desktop: 2-column workspace (schema + main). +- Tablet: collapsible schema; main workflow preserved. +- Mobile: progressive disclosure for secondary tools. +- At constrained widths, preserve visibility of SQL tabs, Run, and database-open flow before secondary utilities. +- Prefer adaptive grouping and overflow menus over uncontrolled toolbar wrapping. + +## Content Voice +- Operational surfaces: concise and neutral. +- Didactic guidance: contextual help, not always-on verbose blocks. +- Empty states and theme actions must avoid playful animations in primary flow. +- Interface language should be consistent within a surface; avoid mixing English labels into Portuguese operational controls unless the term is a conventional technical label. + +## State Persistence UX +- Persist session and preferences in local storage. +- Always expose explicit controls to clear/reset stored UI state. +- For future release: support selective export/import of browser-stored data and preferences with clear scope labels and conflict strategy. + +## Deferred Features (Backlog) +- Favorite instructions UX: +- Save from history to favorites. +- Favorites list with search/filter and quick load to editor. +- Settings portability UX: +- Export selected data scopes (favorites, history, theme, session, SQL tabs). +- Import with preview of selected scopes and merge/replace choice. + +## Acceptance Gates (P0/P1/P2) +- P0: interaction trust (shortcuts, focus, dialogs, keyboard table operations). +- P1: shell hierarchy and responsive density. +- P2: durable systemization (tokens, components, command palette/help, motion standards). diff --git a/index.html b/index.html index 46508d9..b881c05 100644 --- a/index.html +++ b/index.html @@ -189,6 +189,7 @@ select:focus-visible, input:focus-visible, button:focus-visible, .file-label:focus-visible, + summary:focus-visible, [role="button"]:focus-visible { border-color: var(--ring); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ring) 18%, transparent); @@ -367,6 +368,37 @@ opacity: 0.82; } + .empty-state { + min-height: 220px; + display: grid; + place-items: center; + padding: 28px 18px; + color: var(--mutedText); + text-align: center; + } + + .empty-state-card { + width: min(420px, 100%); + display: grid; + gap: 8px; + justify-items: center; + } + + .empty-state-title { + margin: 0; + color: var(--foreground); + font-size: 14px; + font-weight: 800; + letter-spacing: 0; + } + + .empty-state-description { + margin: 0; + color: var(--mutedText); + font-size: 13px; + line-height: 1.45; + } + /* Enhanced SQL syntax highlighting */ html[data-theme="dark"] .CodeMirror .cm-keyword { @@ -663,6 +695,44 @@ accent-color: var(--accentLine); } + .action-btn, + .editor-action-btn, + .file-label.editor-action-btn, + .result-actions .editor-action-btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + min-height: var(--control-height); + padding: 0 12px; + border-radius: calc(var(--radius) - 2px); + line-height: 1; + white-space: nowrap; + } + + .action-btn-sm, + .editor-more-menu .editor-action-btn, + .db-menu-list .editor-action-btn, + .query-history-load-btn, + .schema-type-filter-btn { + min-height: var(--control-height-compact); + padding: 0 10px; + font-size: 12px; + } + + .icon-btn, + .clear-filter-btn, + .clear-schema-search-btn, + .clear-query-history-search-btn, + .toast-close, + .sql-tab-close, + .new-sql-tab-btn { + display: inline-flex; + align-items: center; + justify-content: center; + flex: 0 0 auto; + } + table { border-collapse: separate; border-spacing: 0; @@ -2554,6 +2624,24 @@ border: 1.5px solid var(--panel); box-shadow: 0 0 0 1px color-mix(in srgb, var(--destructive) 35%, transparent); pointer-events: none; + animation: releaseBadgePulse 1.8s ease-in-out infinite; + } + + @keyframes releaseBadgePulse { + 0%, 100% { + transform: scale(1); + opacity: 0.9; + } + 50% { + transform: scale(1.16); + opacity: 1; + } + } + + @media (prefers-reduced-motion: reduce) { + .release-badge { + animation: none; + } } .bug-icon { @@ -3348,12 +3436,6 @@ } } - .offline-card p::after { - content: " A tomada também não está colaborando."; - color: var(--mutedText); - } - - /* beta fix2: didactic bases book icon */ .book-symbol { width: 17px; @@ -4073,9 +4155,56 @@ gap: 6px; flex: 1 1 auto; min-width: 0; + overflow-x: hidden; + overflow-y: hidden; + scrollbar-width: none; + padding-bottom: 2px; + } + + .sql-tabs.is-overflowing { overflow-x: auto; scrollbar-width: thin; - padding-bottom: 2px; + scrollbar-gutter: stable; + } + + .sql-tabs::-webkit-scrollbar { + height: 0; + } + + .sql-tabs.is-overflowing::-webkit-scrollbar { + height: 8px; + } + + .sql-tabs-header { + position: relative; + } + + .sql-tabs-header::before, + .sql-tabs-header::after { + content: ""; + position: absolute; + top: 0; + bottom: 1px; + width: 22px; + pointer-events: none; + z-index: 4; + opacity: 0; + transition: opacity 0.12s ease; + } + + .sql-tabs-header::before { + left: 0; + background: linear-gradient(to right, var(--panel), transparent); + } + + .sql-tabs-header::after { + right: 38px; + background: linear-gradient(to left, var(--panel), transparent); + } + + .sql-tabs-header.can-scroll-left::before, + .sql-tabs-header.can-scroll-right::after { + opacity: 1; } .sql-tab { display: inline-flex; @@ -4500,10 +4629,18 @@ .sql-tabs { gap: 0 !important; padding-bottom: 0 !important; - overflow-x: auto; + overflow-x: hidden; + overflow-y: hidden; + scrollbar-width: none; align-items: flex-end !important; } + .sql-tabs.is-overflowing { + overflow-x: auto; + scrollbar-width: thin; + scrollbar-gutter: stable; + } + .sql-tab { position: relative; max-width: 240px !important; @@ -5825,6 +5962,17 @@ font-weight: 850; } + @media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.001ms !important; + animation-iteration-count: 1 !important; + scroll-behavior: auto !important; + transition-duration: 0.001ms !important; + } + } + @@ -5856,7 +6004,7 @@

hSQLite Editor v0.1.1< Novidades - + @@ -5347,7 +5108,7 @@

7. Reporte de bug

@@ -5358,7 +5119,7 @@

Novidades da versão

Seu editor foi atualizado.

@@ -5408,8 +5169,8 @@

Bases didáticas

@@ -5425,8 +5186,8 @@

Novo Database

@@ -5451,8 +5212,8 @@

Exportar resultado

Não há registros disponíveis para serem exportados.
@@ -6227,7 +5988,9 @@

Sem conexão com a internet

} }, init() { - this.setCollapsed(storage.get(STORAGE_KEYS.SCHEMA_COLLAPSED, "0") === "1"); + const saved = storage.get(STORAGE_KEYS.SCHEMA_COLLAPSED, null); + const prefersCompactSchema = window.matchMedia && window.matchMedia("(max-width: 920px)").matches; + this.setCollapsed(saved === null ? prefersCompactSchema : saved === "1"); }, toggle() { this.setCollapsed(!isSchemaCollapsed); @@ -6533,7 +6296,7 @@

Sem conexão com a internet

if (!editorMoreActions) return; editorMoreActions.addEventListener("toggle", () => { if (!editorMoreActions.open) return; - const firstAction = editorMoreActions.querySelector(".editor-more-menu .editor-action-btn"); + const firstAction = editorMoreActions.querySelector(".editor-more-menu .ui-button"); if (firstAction && typeof firstAction.focus === "function") firstAction.focus(); }); @@ -6542,7 +6305,7 @@

Sem conexão com a internet

if (!editorMoreActions.contains(event.target)) closeEditorMoreActions(); }); - editorMoreActions.querySelectorAll(".editor-more-menu .editor-action-btn").forEach((button) => { + editorMoreActions.querySelectorAll(".editor-more-menu .ui-button").forEach((button) => { button.addEventListener("click", () => closeEditorMoreActions()); }); } @@ -6551,7 +6314,7 @@

Sem conexão com a internet

if (!databaseMenu) return; databaseMenu.addEventListener("toggle", () => { if (!databaseMenu.open) return; - const firstAction = databaseMenu.querySelector(".db-menu-list .editor-action-btn"); + const firstAction = databaseMenu.querySelector(".db-menu-list .ui-button"); if (firstAction && typeof firstAction.focus === "function") firstAction.focus(); }); @@ -7080,7 +6843,7 @@

Sem conexão com a internet

${escapeHtml(title)}
${escapeHtml(message)}
- + `; toast.querySelector(".toast-close").addEventListener("click", () => toast.remove()); toastContainer.appendChild(toast); @@ -7495,10 +7258,10 @@

Sem conexão com a internet

${item.status === "success" - ? `` + ? `` : `` } - +
`; @@ -7579,8 +7342,8 @@

Sem conexão com a internet

${escapeHtml(item.sql)}
- - + +
`).join(""); @@ -8019,8 +7782,8 @@

Sem conexão com a internet

actions.className = "sql-tab-actions"; actions.innerHTML = ` ${isEditing ? `` : ""} - - ${sqlTabs.length > 1 ? '' : ""} + + ${sqlTabs.length > 1 ? '' : ""} `; const input = actions.querySelector(".sql-tab-title-input"); if (input) { @@ -8683,7 +8446,7 @@

Sem conexão com a internet

${escapeHtml(item.name)}
${escapeHtml(secondary || "Arquivo recente")}
- + `; }).join(""); @@ -10703,21 +10466,21 @@

Sem conexão com a internet

const toolbarHtml = `
- +
- - - + + + ${selectedKeys.size} selecionado(s) `; From 4ae49af4e8559dbef74d34dc5c10f0ee0e07d342 Mon Sep 17 00:00:00 2001 From: helbertm Date: Sat, 18 Jul 2026 08:34:54 -0300 Subject: [PATCH 5/8] feat: prepare hSQLite Editor for open-source Linux distribution --- .editorconfig | 12 + .gitattributes | 8 + .github/CODEOWNERS | 7 + .github/ISSUE_TEMPLATE/bug.yml | 60 + .github/ISSUE_TEMPLATE/config.yml | 8 + .github/ISSUE_TEMPLATE/feature.yml | 32 + .github/dependabot.yml | 18 + .github/pull_request_template.md | 24 + .github/workflows/browser-quality.yml | 48 + .github/workflows/codeql.yml | 38 + .github/workflows/commit-convention.yml | 26 +- .github/workflows/dependency-review.yml | 36 + .github/workflows/linux-package.yml | 40 + .github/workflows/pages.yml | 25 +- .github/workflows/quality.yml | 36 + .github/workflows/release-please.yml | 87 +- .gitignore | 9 +- .release-please-manifest.json | 2 +- BACKLOG.md | 62 + CHANGELOG.md | 845 + CODE_OF_CONDUCT.md | 41 + CONTRIBUTING.md | 60 + GOVERNANCE.md | 24 + LICENSE | 21 + README.md | 120 + SECURITY.md | 19 + SUPPORT.md | 13 + THIRD_PARTY_NOTICES.md | 12 + design_system.md | 55 +- docs/accessibility.md | 28 + docs/adr/0001-codemirror-6-editor-runtime.md | 42 + docs/adr/0002-esm-application-module-graph.md | 56 + docs/architecture.md | 45 + docs/linux-packaging.md | 38 + docs/localization.md | 28 + docs/privacy.md | 48 + docs/releasing.md | 26 + docs/remediation-execution-plan.md | 216 + docs/validation.md | 43 + index.html | 46210 ++++++++++++---- package-lock.json | 753 + package.json | 85 + packaging/linux/hsqlite-editor | 42 + .../io.github.helbertm.hsqlite-editor.desktop | 18 + ...ithub.helbertm.hsqlite-editor.metainfo.xml | 40 + .../io.github.helbertm.hsqlite-editor.svg | 7 + portable/inline-badge/README.md | 291 + portable/inline-badge/example.html | 129 + portable/inline-badge/inline-badge.css | 63 + portable/inline-badge/inline-badge.js | 48 + release-please-config.json | 10 +- runtime-components.json | 104 + sbom.spdx.json | 1265 + scripts/app-bundle.mjs | 22 + scripts/build-release.mjs | 23 + scripts/build.mjs | 174 + scripts/bump-version.mjs | 80 + .../database-file-validation.test.mjs | 53 + .../sql-statement-splitter.test.mjs | 37 + scripts/contract-tests/sqlite-types.test.mjs | 35 + .../contract-tests/state-contracts.test.mjs | 89 + scripts/editor-bundle.mjs | 44 + scripts/generate-runtime-components.mjs | 75 + scripts/generate-sbom.mjs | 153 + scripts/linux-package-safety.mjs | 39 + scripts/release-assets.mjs | 53 + scripts/release-utils.mjs | 25 + scripts/run-codex-quality.sh | 23 + scripts/serve-artifact.mjs | 117 + scripts/stage-linux-release.mjs | 185 + scripts/sync-linux-release-metadata.mjs | 60 + scripts/update-vendor.mjs | 87 + scripts/validate-accessibility.mjs | 118 + scripts/validate-approval-gates.mjs | 382 + scripts/validate-artifact.mjs | 224 + scripts/validate-browser-backlog.mjs | 136 + scripts/validate-browser-quality.mjs | 417 + scripts/validate-dependencies.mjs | 45 + scripts/validate-full.mjs | 47 + scripts/validate-i18n.mjs | 362 + scripts/validate-linux-package.mjs | 349 + scripts/validate-linux-system-tools.sh | 36 + scripts/validate-module-graph.mjs | 125 + scripts/validate-native-chromium.mjs | 69 + scripts/validate-privacy-docs.mjs | 53 + scripts/validate-quality-offline.sh | 27 + scripts/validate-release.mjs | 32 + scripts/validate-repository-state.mjs | 129 + scripts/validate-runtime-smoke.mjs | 3766 ++ scripts/validate-security-update.sh | 5 + scripts/validate-settings-transfer.mjs | 90 + scripts/validate-source.mjs | 274 + scripts/validate-workflows.mjs | 46 + scripts/vendor-utils.mjs | 85 + security_posture.md | 39 + src/app.mjs | 7 + src/capabilities/00-dom-base.js | 17 + src/capabilities/01-dom-layout-schema.js | 19 + src/capabilities/01-inline-badge.js | 43 + src/capabilities/02-dom-database.js | 17 + src/capabilities/02-runtime-loaders.js | 29 + src/capabilities/02a-offline-mode.js | 9 + src/capabilities/02b-editor-focus.js | 14 + src/capabilities/02c-shell-bootstrap-ui.js | 59 + src/capabilities/03-dom-editor-results.js | 50 + src/capabilities/03-localization.js | 173 + src/capabilities/03a-localization-messages.js | 463 + src/capabilities/05-dom-library-settings.js | 48 + src/capabilities/05-modal-controller.js | 112 + .../05a-result-state-controller.js | 61 + src/capabilities/05b-database-dirty.js | 28 + src/capabilities/05c-result-scrollbar.js | 57 + src/capabilities/06-dom-sql-map.js | 44 + src/capabilities/06-sql-runtime.js | 12 + src/capabilities/07-database-runtime.js | 59 + src/capabilities/07-dom-table-population.js | 10 + src/capabilities/10-release-metadata.js | 186 + src/capabilities/10-sql-execution.js | 294 + src/capabilities/12-shell-status.js | 36 + src/capabilities/13-schema-panel.js | 40 + src/capabilities/14-app-boot.js | 117 + src/capabilities/15-preferences.js | 177 + src/capabilities/19-history-formatting.js | 27 + src/capabilities/20-history-query.js | 163 + src/capabilities/21-history-favorites.js | 89 + src/capabilities/21a-settings-transfer.js | 194 + src/capabilities/22-sql-tabs-storage.js | 69 + src/capabilities/22a-sql-tab-presets.js | 65 + src/capabilities/22b-sql-tab-factory.js | 47 + src/capabilities/22c-active-tab-sync.js | 32 + src/capabilities/23-sql-tabs-state.js | 209 + src/capabilities/24-sql-tabs-render.js | 303 + src/capabilities/25-shell-shortcuts.js | 192 + .../30-database-session-storage.js | 117 + .../31-database-session-runtime.js | 263 + .../32-database-file-validation.js | 77 + src/capabilities/32-editor-runtime.js | 95 + .../32a-database-file-constants.js | 2 + src/capabilities/32a-editor-api.js | 43 + src/capabilities/32b-editor-feedback.js | 104 + src/capabilities/33-editor-selection.js | 19 + src/capabilities/35-editor-quick-history.js | 112 + src/capabilities/36-editor-file-workflow.js | 130 + src/capabilities/37-editor-actions.js | 131 + src/capabilities/39-table-population.js | 317 + src/capabilities/40-sql-find.js | 234 + src/capabilities/44-sql-map-constants.js | 5 + src/capabilities/45-sql-map-core.js | 414 + src/capabilities/45a-sql-map-runtime.js | 51 + src/capabilities/45b-sql-map-tooltip.js | 25 + src/capabilities/46-sql-map-graph.js | 286 + src/capabilities/47-sql-map-render.js | 602 + src/capabilities/48-sql-map-interactions.js | 409 + src/core/00-contracts.js | 173 + src/core/01-format-duration.js | 9 + src/core/02-locales.js | 2 + src/core/03-app-limits.js | 2 + src/core/04-tab-name-presets.js | 11 + src/core/05-settings-import-contract.js | 172 + src/core/05-sql-statement-splitter.js | 74 + src/core/06-sqlite-types.js | 22 + src/core/07-sql-escaping.js | 13 + src/core/08-runtime-config.js | 43 + src/core/09-test-hooks.js | 24 + src/core/10-state-root.js | 86 + src/core/11-state-tabs.js | 101 + src/core/12-state-grid-results.js | 224 + src/core/13-state-preferences.js | 61 + src/core/14-state-database-schema.js | 99 + src/core/15-state-runtime-library.js | 92 + src/editor/codemirror6-adapter.mjs | 306 + src/index.template.html | 842 + src/ports/05-storage.js | 141 + src/ports/10-browser-io.js | 50 + src/ports/20-sql-worker.js | 345 + src/ports/30-file-access.js | 84 + src/styles/00-tokens.css | 126 + src/styles/01-base.css | 168 + src/styles/02-layout.css | 145 + src/styles/03-components.css | 2017 + src/styles/10-feature-schema.css | 299 + src/styles/11-feature-editor.css | 489 + src/styles/12-feature-results.css | 907 + src/styles/13-feature-session-settings.css | 245 + src/styles/14-feature-sql-map.css | 622 + src/styles/15-feature-boot-offline.css | 152 + src/test-api.mjs | 92 + src/ui/00-helpers.js | 20 + src/ui/05-localization-refresh.js | 32 + src/ui/09-schema-constants.js | 28 + src/ui/10-schema.js | 324 + src/ui/20-results-state.js | 236 + src/ui/21-results-toolbar.js | 124 + src/ui/22-results-table.js | 615 + src/ui/23-results-export.js | 112 + src/ui/30-autocomplete.js | 317 + src/ui/40-database-actions.js | 224 + src/ui/70-bindings-database.js | 56 + src/ui/71-bindings-library.js | 92 + src/ui/72-bindings-advanced-ui.js | 137 + src/ui/80-bindings.js | 75 + vendor/manifest.json | 18 + vendor/sql.js/1.14.1/sql-wasm.js | 185 + vendor/sql.js/1.14.1/sql-wasm.wasm | Bin 0 -> 659730 bytes 204 files changed, 67523 insertions(+), 9970 deletions(-) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/CODEOWNERS create mode 100644 .github/ISSUE_TEMPLATE/bug.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature.yml create mode 100644 .github/dependabot.yml create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/browser-quality.yml create mode 100644 .github/workflows/codeql.yml create mode 100644 .github/workflows/dependency-review.yml create mode 100644 .github/workflows/linux-package.yml create mode 100644 .github/workflows/quality.yml create mode 100644 BACKLOG.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 GOVERNANCE.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 SECURITY.md create mode 100644 SUPPORT.md create mode 100644 THIRD_PARTY_NOTICES.md create mode 100644 docs/accessibility.md create mode 100644 docs/adr/0001-codemirror-6-editor-runtime.md create mode 100644 docs/adr/0002-esm-application-module-graph.md create mode 100644 docs/architecture.md create mode 100644 docs/linux-packaging.md create mode 100644 docs/localization.md create mode 100644 docs/privacy.md create mode 100644 docs/releasing.md create mode 100644 docs/remediation-execution-plan.md create mode 100644 docs/validation.md create mode 100644 package-lock.json create mode 100644 package.json create mode 100755 packaging/linux/hsqlite-editor create mode 100644 packaging/linux/io.github.helbertm.hsqlite-editor.desktop create mode 100644 packaging/linux/io.github.helbertm.hsqlite-editor.metainfo.xml create mode 100644 packaging/linux/io.github.helbertm.hsqlite-editor.svg create mode 100644 portable/inline-badge/README.md create mode 100644 portable/inline-badge/example.html create mode 100644 portable/inline-badge/inline-badge.css create mode 100644 portable/inline-badge/inline-badge.js create mode 100644 runtime-components.json create mode 100644 sbom.spdx.json create mode 100644 scripts/app-bundle.mjs create mode 100644 scripts/build-release.mjs create mode 100644 scripts/build.mjs create mode 100644 scripts/bump-version.mjs create mode 100644 scripts/contract-tests/database-file-validation.test.mjs create mode 100644 scripts/contract-tests/sql-statement-splitter.test.mjs create mode 100644 scripts/contract-tests/sqlite-types.test.mjs create mode 100644 scripts/contract-tests/state-contracts.test.mjs create mode 100644 scripts/editor-bundle.mjs create mode 100644 scripts/generate-runtime-components.mjs create mode 100644 scripts/generate-sbom.mjs create mode 100644 scripts/linux-package-safety.mjs create mode 100644 scripts/release-assets.mjs create mode 100644 scripts/release-utils.mjs create mode 100755 scripts/run-codex-quality.sh create mode 100644 scripts/serve-artifact.mjs create mode 100644 scripts/stage-linux-release.mjs create mode 100644 scripts/sync-linux-release-metadata.mjs create mode 100644 scripts/update-vendor.mjs create mode 100644 scripts/validate-accessibility.mjs create mode 100644 scripts/validate-approval-gates.mjs create mode 100644 scripts/validate-artifact.mjs create mode 100644 scripts/validate-browser-backlog.mjs create mode 100644 scripts/validate-browser-quality.mjs create mode 100644 scripts/validate-dependencies.mjs create mode 100644 scripts/validate-full.mjs create mode 100644 scripts/validate-i18n.mjs create mode 100644 scripts/validate-linux-package.mjs create mode 100755 scripts/validate-linux-system-tools.sh create mode 100644 scripts/validate-module-graph.mjs create mode 100644 scripts/validate-native-chromium.mjs create mode 100644 scripts/validate-privacy-docs.mjs create mode 100755 scripts/validate-quality-offline.sh create mode 100644 scripts/validate-release.mjs create mode 100644 scripts/validate-repository-state.mjs create mode 100644 scripts/validate-runtime-smoke.mjs create mode 100644 scripts/validate-security-update.sh create mode 100644 scripts/validate-settings-transfer.mjs create mode 100644 scripts/validate-source.mjs create mode 100644 scripts/validate-workflows.mjs create mode 100644 scripts/vendor-utils.mjs create mode 100644 security_posture.md create mode 100644 src/app.mjs create mode 100644 src/capabilities/00-dom-base.js create mode 100644 src/capabilities/01-dom-layout-schema.js create mode 100644 src/capabilities/01-inline-badge.js create mode 100644 src/capabilities/02-dom-database.js create mode 100644 src/capabilities/02-runtime-loaders.js create mode 100644 src/capabilities/02a-offline-mode.js create mode 100644 src/capabilities/02b-editor-focus.js create mode 100644 src/capabilities/02c-shell-bootstrap-ui.js create mode 100644 src/capabilities/03-dom-editor-results.js create mode 100644 src/capabilities/03-localization.js create mode 100644 src/capabilities/03a-localization-messages.js create mode 100644 src/capabilities/05-dom-library-settings.js create mode 100644 src/capabilities/05-modal-controller.js create mode 100644 src/capabilities/05a-result-state-controller.js create mode 100644 src/capabilities/05b-database-dirty.js create mode 100644 src/capabilities/05c-result-scrollbar.js create mode 100644 src/capabilities/06-dom-sql-map.js create mode 100644 src/capabilities/06-sql-runtime.js create mode 100644 src/capabilities/07-database-runtime.js create mode 100644 src/capabilities/07-dom-table-population.js create mode 100644 src/capabilities/10-release-metadata.js create mode 100644 src/capabilities/10-sql-execution.js create mode 100644 src/capabilities/12-shell-status.js create mode 100644 src/capabilities/13-schema-panel.js create mode 100644 src/capabilities/14-app-boot.js create mode 100644 src/capabilities/15-preferences.js create mode 100644 src/capabilities/19-history-formatting.js create mode 100644 src/capabilities/20-history-query.js create mode 100644 src/capabilities/21-history-favorites.js create mode 100644 src/capabilities/21a-settings-transfer.js create mode 100644 src/capabilities/22-sql-tabs-storage.js create mode 100644 src/capabilities/22a-sql-tab-presets.js create mode 100644 src/capabilities/22b-sql-tab-factory.js create mode 100644 src/capabilities/22c-active-tab-sync.js create mode 100644 src/capabilities/23-sql-tabs-state.js create mode 100644 src/capabilities/24-sql-tabs-render.js create mode 100644 src/capabilities/25-shell-shortcuts.js create mode 100644 src/capabilities/30-database-session-storage.js create mode 100644 src/capabilities/31-database-session-runtime.js create mode 100644 src/capabilities/32-database-file-validation.js create mode 100644 src/capabilities/32-editor-runtime.js create mode 100644 src/capabilities/32a-database-file-constants.js create mode 100644 src/capabilities/32a-editor-api.js create mode 100644 src/capabilities/32b-editor-feedback.js create mode 100644 src/capabilities/33-editor-selection.js create mode 100644 src/capabilities/35-editor-quick-history.js create mode 100644 src/capabilities/36-editor-file-workflow.js create mode 100644 src/capabilities/37-editor-actions.js create mode 100644 src/capabilities/39-table-population.js create mode 100644 src/capabilities/40-sql-find.js create mode 100644 src/capabilities/44-sql-map-constants.js create mode 100644 src/capabilities/45-sql-map-core.js create mode 100644 src/capabilities/45a-sql-map-runtime.js create mode 100644 src/capabilities/45b-sql-map-tooltip.js create mode 100644 src/capabilities/46-sql-map-graph.js create mode 100644 src/capabilities/47-sql-map-render.js create mode 100644 src/capabilities/48-sql-map-interactions.js create mode 100644 src/core/00-contracts.js create mode 100644 src/core/01-format-duration.js create mode 100644 src/core/02-locales.js create mode 100644 src/core/03-app-limits.js create mode 100644 src/core/04-tab-name-presets.js create mode 100644 src/core/05-settings-import-contract.js create mode 100644 src/core/05-sql-statement-splitter.js create mode 100644 src/core/06-sqlite-types.js create mode 100644 src/core/07-sql-escaping.js create mode 100644 src/core/08-runtime-config.js create mode 100644 src/core/09-test-hooks.js create mode 100644 src/core/10-state-root.js create mode 100644 src/core/11-state-tabs.js create mode 100644 src/core/12-state-grid-results.js create mode 100644 src/core/13-state-preferences.js create mode 100644 src/core/14-state-database-schema.js create mode 100644 src/core/15-state-runtime-library.js create mode 100644 src/editor/codemirror6-adapter.mjs create mode 100644 src/index.template.html create mode 100644 src/ports/05-storage.js create mode 100644 src/ports/10-browser-io.js create mode 100644 src/ports/20-sql-worker.js create mode 100644 src/ports/30-file-access.js create mode 100644 src/styles/00-tokens.css create mode 100644 src/styles/01-base.css create mode 100644 src/styles/02-layout.css create mode 100644 src/styles/03-components.css create mode 100644 src/styles/10-feature-schema.css create mode 100644 src/styles/11-feature-editor.css create mode 100644 src/styles/12-feature-results.css create mode 100644 src/styles/13-feature-session-settings.css create mode 100644 src/styles/14-feature-sql-map.css create mode 100644 src/styles/15-feature-boot-offline.css create mode 100644 src/test-api.mjs create mode 100644 src/ui/00-helpers.js create mode 100644 src/ui/05-localization-refresh.js create mode 100644 src/ui/09-schema-constants.js create mode 100644 src/ui/10-schema.js create mode 100644 src/ui/20-results-state.js create mode 100644 src/ui/21-results-toolbar.js create mode 100644 src/ui/22-results-table.js create mode 100644 src/ui/23-results-export.js create mode 100644 src/ui/30-autocomplete.js create mode 100644 src/ui/40-database-actions.js create mode 100644 src/ui/70-bindings-database.js create mode 100644 src/ui/71-bindings-library.js create mode 100644 src/ui/72-bindings-advanced-ui.js create mode 100644 src/ui/80-bindings.js create mode 100644 vendor/manifest.json create mode 100644 vendor/sql.js/1.14.1/sql-wasm.js create mode 100644 vendor/sql.js/1.14.1/sql-wasm.wasm diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1014ba7 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..02c8fa5 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,8 @@ +* text=auto eol=lf + +*.db binary +*.db3 binary +*.s3db binary +*.sqlite binary +*.sqlite3 binary +*.wasm binary diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..0024dd2 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,7 @@ +* @helbertm + +/.github/ @helbertm +/scripts/ @helbertm +/src/core/ @helbertm +/src/ports/ @helbertm +/vendor/ @helbertm diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml new file mode 100644 index 0000000..7d58fa9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -0,0 +1,60 @@ +name: Bug report +description: Report a reproducible product defect +title: "[Bug]: " +labels: ["bug", "triage"] +body: + - type: markdown + attributes: + value: Do not include confidential database contents. Report vulnerabilities through the private security process. + - type: textarea + id: summary + attributes: + label: Summary + description: What happened, and what did you expect? + validations: + required: true + - type: textarea + id: steps + attributes: + label: Reproduction steps + description: Provide the smallest reliable sequence. + placeholder: "1. Open ...\n2. Run ...\n3. Observe ..." + validations: + required: true + - type: input + id: version + attributes: + label: hSQLite Editor version + placeholder: 0.3.143 + validations: + required: true + - type: input + id: environment + attributes: + label: Browser and operating system + placeholder: Safari 19 on macOS 16 + validations: + required: true + - type: dropdown + id: launch + attributes: + label: Launch mode + options: + - file:// standalone artifact + - GitHub Pages + - Local loopback server + - Other + validations: + required: true + - type: textarea + id: evidence + attributes: + label: Additional evidence + description: Sanitized screenshots, console output, or a synthetic database. + - type: checkboxes + id: confirmations + attributes: + label: Confirmation + options: + - label: I reproduced this on the latest release and removed confidential data. + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..7ab3bf2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Security vulnerability + url: https://github.com/helbertm/hSQLite-Editor/security/advisories/new + about: Report security vulnerabilities privately. + - name: Usage question or design discussion + url: https://github.com/helbertm/hSQLite-Editor/discussions + about: Ask for help or discuss broader ideas. diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml new file mode 100644 index 0000000..c44883a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -0,0 +1,32 @@ +name: Feature request +description: Propose a scoped product improvement +title: "[Feature]: " +labels: ["enhancement", "triage"] +body: + - type: textarea + id: problem + attributes: + label: Problem + description: Describe the user need, not only a preferred implementation. + validations: + required: true + - type: textarea + id: proposal + attributes: + label: Proposed outcome + description: What should become possible or easier? + validations: + required: true + - type: textarea + id: alternatives + attributes: + label: Alternatives considered + - type: checkboxes + id: constraints + attributes: + label: Project constraints + options: + - label: The proposal can preserve local-first operation and the standalone offline artifact. + required: true + - label: I considered keyboard, accessibility, and all supported locales. + required: true diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..8b5df0f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,18 @@ +version: 2 +updates: + - package-ecosystem: npm + directory: / + schedule: + interval: monthly + open-pull-requests-limit: 5 + labels: + - dependencies + + - package-ecosystem: github-actions + directory: / + schedule: + interval: monthly + open-pull-requests-limit: 5 + labels: + - dependencies + - ci diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..eaa7479 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,24 @@ +## Problem + + + +## Approach + + + +## Verification + +- [ ] `npm run validate:full` +- [ ] Changed behavior tested in a real browser +- [ ] Standalone `file://` contract preserved + +## Quality impact + +- Accessibility: +- Localization (`pt-BR`, `es-ES`, `en-US`): +- Security/privacy: +- Performance/data integrity: + +## Residual risk + + diff --git a/.github/workflows/browser-quality.yml b/.github/workflows/browser-quality.yml new file mode 100644 index 0000000..4e18da2 --- /dev/null +++ b/.github/workflows/browser-quality.yml @@ -0,0 +1,48 @@ +name: Browser Quality + +on: + pull_request: + branches: [master] + push: + branches: [master] + +permissions: + contents: read + +concurrency: + group: browser-quality-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + locale-accessibility: + runs-on: ubuntu-latest + timeout-minutes: 25 + steps: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - name: Setup Node.js + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 + with: + node-version: 22 + cache: npm + + - name: Install dependencies and Chromium + run: | + npm ci + npx playwright install --with-deps chromium + + - name: Build and run browser quality matrix + run: | + npm run build:release + npm run serve:artifact & + SERVER_PID=$! + trap 'kill "$SERVER_PID"' EXIT + for attempt in {1..30}; do + if curl --fail --silent http://127.0.0.1:4173/ > /dev/null; then + break + fi + sleep 1 + done + RELEASE_VERSION="$(node -p 'require("./package.json").version')" + HSQLITE_BASE_URL="http://127.0.0.1:4173/dist/hSQLite-Editor-v${RELEASE_VERSION}.html" npm run validate:browser:quality diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..70af7e8 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,38 @@ +name: CodeQL + +on: + push: + branches: [master] + pull_request: + branches: [master] + schedule: + - cron: "17 4 * * 2" + +permissions: + contents: read + security-events: write + +concurrency: + group: codeql-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + analyze: + name: Analyze JavaScript + runs-on: ubuntu-latest + timeout-minutes: 20 + permissions: + actions: read + contents: read + security-events: write + steps: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - name: Initialize CodeQL + uses: github/codeql-action/init@7188fc363630916deb702c7fdcf4e481b751f97a # v4.37.1 + with: + languages: javascript-typescript + + - name: Analyze + uses: github/codeql-action/analyze@7188fc363630916deb702c7fdcf4e481b751f97a # v4.37.1 diff --git a/.github/workflows/commit-convention.yml b/.github/workflows/commit-convention.yml index e909add..b118584 100644 --- a/.github/workflows/commit-convention.yml +++ b/.github/workflows/commit-convention.yml @@ -8,12 +8,20 @@ on: branches: - master +permissions: + contents: read + +concurrency: + group: commit-convention-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: conventional-commits: runs-on: ubuntu-latest + timeout-minutes: 10 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: fetch-depth: 0 @@ -55,21 +63,19 @@ jobs: fi if [[ ! "$SUBJECT" =~ $CONVENTIONAL_REGEX ]]; then - echo "❌ Commit inválido: $COMMIT" - echo " Mensagem: $SUBJECT" + echo "Invalid commit: $COMMIT" + echo "Subject: $SUBJECT" FAIL=1 fi done <<< "$COMMITS" if [[ "$FAIL" -ne 0 ]]; then echo "" - echo "Use o padrão Conventional Commits:" - echo " feat: descrição" - echo " fix: descrição" - echo " chore: descrição" - echo "Exemplo amigável:" - echo " fix: Correção do texto das novidades no release de versão" + echo "Use Conventional Commits:" + echo " feat: description" + echo " fix: description" + echo " chore: description" exit 1 fi - echo "✅ Todas as mensagens de commit estão válidas." + echo "All commit messages are valid." diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000..f98b4b3 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,36 @@ +name: Dependency Review + +on: + pull_request: + branches: [master] + +permissions: + contents: read + +concurrency: + group: dependency-review-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + dependency-review: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - name: Setup Node.js + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 + with: + node-version: 22 + cache: npm + + - name: Validate locked dependencies + run: | + npm ci + npm run validate:dependencies + + - name: Review dependency changes + uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0 + with: + fail-on-severity: high diff --git a/.github/workflows/linux-package.yml b/.github/workflows/linux-package.yml new file mode 100644 index 0000000..35ff8e9 --- /dev/null +++ b/.github/workflows/linux-package.yml @@ -0,0 +1,40 @@ +name: Linux Package + +on: + pull_request: + branches: [master] + push: + branches: [master] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: linux-package-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + validate: + runs-on: ubuntu-24.04 + timeout-minutes: 20 + steps: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - name: Setup Node.js + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 + with: + node-version: 22 + cache: npm + + - name: Install exact JavaScript dependencies + run: npm ci + + - name: Install freedesktop.org validators + run: | + sudo apt-get update + sudo apt-get install --no-install-recommends appstream desktop-file-utils xdg-utils + + - name: Validate Linux package stage + run: npm run validate:linux:system diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 612041c..1e74479 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -8,8 +8,6 @@ on: permissions: contents: read - pages: write - id-token: write concurrency: group: pages @@ -18,9 +16,21 @@ concurrency: jobs: build: runs-on: ubuntu-latest + timeout-minutes: 15 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - name: Setup Node.js + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 + with: + node-version: 22 + + - name: Validate and build standalone artifacts + run: | + npm ci + npm run validate:dependencies + npm run validate:full:ci - name: Prepare site run: | @@ -30,17 +40,22 @@ jobs: cp .release-please-manifest.json _site/.release-please-manifest.json - name: Upload artifact - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0 with: path: _site deploy: needs: build runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + pages: write + id-token: write environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml new file mode 100644 index 0000000..216595c --- /dev/null +++ b/.github/workflows/quality.yml @@ -0,0 +1,36 @@ +name: Quality Gate + +on: + pull_request: + branches: [master] + push: + branches: [master] + +permissions: + contents: read + +concurrency: + group: quality-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + validate: + runs-on: ubuntu-latest + timeout-minutes: 25 + steps: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - name: Setup Node.js + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 + with: + node-version: 22 + cache: npm + + - name: Install exact dependencies + run: npm ci + + - name: Validate release candidate + run: | + npm run validate:dependencies + npm run validate:full:ci diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 00b3ce2..70483f1 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -6,15 +6,96 @@ on: - master permissions: - contents: write - pull-requests: write + contents: read + +concurrency: + group: release-${{ github.ref }} + cancel-in-progress: false jobs: + preflight: + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - name: Setup Node.js + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 + with: + node-version: 22 + + - name: Validate release pipeline + run: | + npm ci + npm run validate:dependencies + npm run validate:full:ci + release-please: + needs: preflight runs-on: ubuntu-latest + timeout-minutes: 20 + permissions: + contents: write + pull-requests: write + outputs: + release_created: ${{ steps.release.outputs.release_created }} + tag_name: ${{ steps.release.outputs.tag_name }} + version: ${{ steps.release.outputs.version }} steps: - name: Release Please - uses: googleapis/release-please-action@v4 + id: release + uses: googleapis/release-please-action@5c625bfb5d1ff62eadeeb3772007f7f66fdcf071 # v4.4.1 with: config-file: release-please-config.json manifest-file: .release-please-manifest.json + + publish-assets: + needs: release-please + if: needs.release-please.outputs.release_created == 'true' + runs-on: ubuntu-latest + timeout-minutes: 20 + permissions: + attestations: write + contents: write + id-token: write + steps: + - name: Checkout released source + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + ref: ${{ needs.release-please.outputs.tag_name }} + + - name: Setup Node.js + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 + with: + node-version: 22 + + - name: Build and verify release assets + run: | + npm ci + npm run validate:dependencies + npm run validate:full + npm run generate:sbom + npm run generate:release-checksums + npm run validate:release-assets + + - name: Attest release provenance + uses: actions/attest@f7c74d28b9d84cb8768d0b8ca14a4bac6ef463e6 # v4.2.0 + with: + subject-path: dist/hSQLite-Editor-v${{ needs.release-please.outputs.version }}.html + + - name: Attest release SPDX SBOM + uses: actions/attest@f7c74d28b9d84cb8768d0b8ca14a4bac6ef463e6 # v4.2.0 + with: + subject-path: dist/hSQLite-Editor-v${{ needs.release-please.outputs.version }}.html + sbom-path: sbom.spdx.json + + - name: Upload release assets + env: + GH_TOKEN: ${{ github.token }} + run: >- + gh release upload "${{ needs.release-please.outputs.tag_name }}" + "dist/hSQLite-Editor-v${{ needs.release-please.outputs.version }}.html" + sbom.spdx.json + SHA256SUMS + --clobber diff --git a/.gitignore b/.gitignore index 335ccc8..710d62d 100644 --- a/.gitignore +++ b/.gitignore @@ -16,10 +16,15 @@ node_modules/ dist/ coverage/ +playwright-report/ +test-results/ +_site/ +/SHA256SUMS -# Specialist artifacts -/agent-state/*/reports/ +# Local agent continuity and specialist artifacts +/agent-state/ /burlemarx/ /davinci/ /angela-jobson/ /linus-swartz/ +/.codex/ diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 0477999..dc96ffd 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.3.2" + ".": "0.3.143" } diff --git a/BACKLOG.md b/BACKLOG.md new file mode 100644 index 0000000..0310812 --- /dev/null +++ b/BACKLOG.md @@ -0,0 +1,62 @@ +# Product Backlog + +This file records product work requested or accepted as part of the cleanup plan and its delivery status. + +## Data Integrity + +### Virtual FK orphan validation +- Status: implemented +- Goal: block creation of a virtual FK when the proposed relationship would connect orphan records on either side of the join. +- Expected behavior: + - validate real data compatibility before persisting the virtual FK + - if orphan rows exist, do not create the relationship + - show an explicit warning explaining why creation was blocked + - generate a diagnostic SQL query that lists the orphan rows responsible for the block +- Rationale: + - keeps the SQL Map surface honest + - prevents the editor from suggesting a relationship that real data does not support +- Verification: + - worker-based bidirectional orphan preflight blocks invalid relationships + - the blocking dialog exposes diagnostic SQL for the incompatible rows + +## SQL Map UX + +### Floating drag affordance for virtual FK creation +- Status: implemented +- Goal: when the user drags one field onto another in the SQL Map, the relationship should visually follow the pointer instead of appearing only after drop. +- Expected behavior: + - render a floating relationship draft that tracks the cursor + - preserve readable source/target hover states during the drag + - keep the effect lightweight and legible rather than ornamental +- Rationale: + - improves perceived direct manipulation + - makes the virtual FK gesture easier to understand before drop +- Verification: + - an SVG draft edge follows the pointer and highlights compatible targets + - the same relationship workflow is available with keyboard focus, Enter/Space, and Escape + +## QA Tooling + +### Table population workflow for synthetic data +- Status: implemented +- Goal: add a QA-oriented table seeding workflow so users can populate a chosen table with configurable volumes and per-column generation rules. +- Expected behavior: + - inspect the selected table schema and list the columns before insertion + - keep PK fields on the automatic path by default + - allow per-column strategies based on type, including: + - fixed numeric values + - numeric increments with configurable start/step + - random numeric ranges + - fixed text + - random or lorem-style text + - other type-appropriate strategies introduced later + - let the user define the target record count + - insert the requested number of rows into the current database +- Intended use: + - QA data setup + - performance and load experiments against app databases + - local stress tests such as `100_000` or `1_000_000` row scenarios +- Verification: + - table actions open a schema-aware configuration dialog with type-specific strategies + - insertion runs in one worker transaction with progress, rollback, cancellation, and a `1_000_000` row ceiling + - volumes above `100_000` rows require explicit confirmation diff --git a/CHANGELOG.md b/CHANGELOG.md index 0331d69..23c299d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,850 @@ # Changelog +## [0.3.143](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.142...hsqlite-editor-v0.3.143) (2026-06-12) + +### Features + +* replace the query-history load label with an icon-only action button while preserving hover hint and accessibility labeling + +## [0.3.142](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.141...hsqlite-editor-v0.3.142) (2026-06-12) + +### Features + +* compact the query-history favorite/load actions into a horizontal layout with a dedicated square favorite control + +## [0.3.141](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.140...hsqlite-editor-v0.3.141) (2026-06-12) + +### Features + +* expand SQL Map natural-FK drag suggestions to accepted naming families such as id, uuid, *_id, *_uuid, cod*, and codigo* + +## [0.3.140](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.139...hsqlite-editor-v0.3.140) (2026-06-12) + +### Features + +* highlight natural virtual-FK destination suggestions during SQL Map field drag when other tables expose the same field name and type class + +## [0.3.139](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.138...hsqlite-editor-v0.3.139) (2026-06-12) + +### Features + +* change SQL Map virtual-FK drag affordance so the source field itself floats with the pointer instead of rendering a provisional line + +## [0.3.138](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.137...hsqlite-editor-v0.3.138) (2026-06-12) + +### Features + +* block virtual FK creation on SQL Map orphaned data with diagnostic SQL, and add a provisional drag edge with explicit allowed/caution/blocked target feedback + +## [0.3.137](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.136...hsqlite-editor-v0.3.137) (2026-06-12) + +### Features + +* record direct native Safari `file://` verification evidence in the completion audits and close the final offline-contract review gap + +## [0.3.136](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.135...hsqlite-editor-v0.3.136) (2026-06-12) + +### Features + +* document a repo-owned native `file://` verification checklist so the remaining offline-proof gap is explicit and operationally bounded + +## [0.3.135](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.134...hsqlite-editor-v0.3.135) (2026-06-11) + +### Features + +* remove the extra `src/app` layer by consolidating orchestration and feature modules under `src/capabilities`, aligning the source tree to the four-layer architecture contract + +## [0.3.134](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.133...hsqlite-editor-v0.3.134) (2026-06-11) + +### Features + +* record stronger browser-level approval evidence for the generated artifact and document the current browser-runtime CodeMirror typing limitation as harness scope, not product behavior + +## [0.3.133](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.132...hsqlite-editor-v0.3.133) (2026-06-11) + +### Features + +* move SQL tab shuffled-name allocation into the explicit tab state contract instead of leaving it in a hidden module-local runtime variable + +## [0.3.132](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.131...hsqlite-editor-v0.3.132) (2026-06-11) + +### Features + +* move embedded runtime config, live SQLite runtime cache, and SQL Map drag-hover runtime out of `src/core/10-state.js`, further shrinking the remaining core state surface + +## [0.3.131](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.130...hsqlite-editor-v0.3.131) (2026-06-11) + +### Features + +* add a repo-owned approval-gate validator, wire it into the release flow, and tighten docs/audit drift around the open-source approval contract + +## [0.3.130](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.129...hsqlite-editor-v0.3.130) (2026-06-11) + +### Features + +* move tab-name presets and several domain constant catalogs out of `src/core/10-state.js` into feature-scoped source files, reducing the remaining core god-file surface + +## [0.3.129](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.128...hsqlite-editor-v0.3.129) (2026-06-11) + +### Features + +* split the large UI binding block into feature-scoped modules so `src/ui/80-bindings.js` remains a thin post-boot composition entrypoint + +## [0.3.128](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.127...hsqlite-editor-v0.3.128) (2026-06-11) + +### Features + +* move browser file-picker and persisted file-handle adapters into `src/ports/30-file-access.js`, removing raw `showOpenFilePicker()` and IndexedDB handle-store code from DB session modules + +## [0.3.127](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.126...hsqlite-editor-v0.3.127) (2026-06-11) + +### Features + +* move visible SQL execution/export runtime state into `appState.runtime` and relocate non-serializable worker/timer handles into an explicit app runtime helper instead of leaving them in the core state module + +## [0.3.126](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.125...hsqlite-editor-v0.3.126) (2026-06-11) + +### Features + +* move editor quick-history selection and SQL find/replace state into `appState.editor`, reducing more of the old monolithic runtime authority outside the central state container + +## [0.3.125](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.124...hsqlite-editor-v0.3.125) (2026-06-11) + +### Features + +* move SQL tab control flags and deferred SQL-file execution intent into `appState`, reducing remaining UI/runtime authority outside the central state model + +## [0.3.124](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.123...hsqlite-editor-v0.3.124) (2026-06-11) + +### Features + +* move embedded SQL worker creation/disposal into `src/ports/20-sql-worker.js`, so SQL execution orchestration no longer owns browser worker adapter construction inline + +## [0.3.123](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.122...hsqlite-editor-v0.3.123) (2026-06-11) + +### Features + +* move browser persistence keys, migrations, and helper storages out of the core state module into `src/ports/05-storage.js`, keeping the single-file offline artifact contract intact + +## [0.3.122](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.121...hsqlite-editor-v0.3.122) (2026-06-11) + +### Features + +* move persisted session/tab-preset/schema preference ownership into `appState.preferences` instead of leaving those values in free-floating globals + +## [0.3.121](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.120...hsqlite-editor-v0.3.121) (2026-06-11) + +### Features + +* formalize the active SQLite connection as an explicit runtime cache and move canonical SQL Map state into `appState`, leaving only drag/hover interaction data outside the central state container + +## [0.3.120](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.119...hsqlite-editor-v0.3.120) (2026-06-11) + +### Features + +* move loaded schema ownership into `appState` and remove schema globals from the core runtime contract + +## [0.3.119](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.118...hsqlite-editor-v0.3.119) (2026-06-11) + +### Features + +* preserve the active session when direct file-input DB selection fails, cover that path in runtime smoke, and formalize accepted deferred work in a repo backlog + +## [0.3.118](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.117...hsqlite-editor-v0.3.118) (2026-06-11) + +### Features + +* remove the tab-action button backgrounds and harden runtime smoke coverage for generated empty-database execution + +## [0.3.117](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.116...hsqlite-editor-v0.3.117) (2026-06-11) + +### Features + +* extend runtime smoke so the visible `Novo` flow is proven through SQL execution, schema refresh, result rendering, and export enablement inside the generated empty database + +## [0.3.116](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.115...hsqlite-editor-v0.3.116) (2026-06-11) + +### Features + +* harden source validation so the empty generated-database exception cannot leak into normal SQLite file-validation paths + +## [0.3.115](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.114...hsqlite-editor-v0.3.115) (2026-06-11) + +### Features + +* make mixed multi-statement execution activate the first tabular result set by default so export actions stay enabled when the final visible result is a table + +## [0.3.114](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.113...hsqlite-editor-v0.3.114) (2026-06-11) + +### Features + +* record real-browser proof that the generated empty-database flow can execute SQL, update schema, and render query results on the served artifact + +## [0.3.113](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.112...hsqlite-editor-v0.3.113) (2026-06-11) + +### Features + +* fix the visible “Novo banco” flow so editor-generated empty databases are accepted, and add repo-owned smoke coverage for that path + +## [0.3.112](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.111...hsqlite-editor-v0.3.112) (2026-06-11) + +### Features + +* add a repo-owned loopback artifact server for real-browser verification and document that review path as part of the approval workflow + +## [0.3.111](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.110...hsqlite-editor-v0.3.111) (2026-06-11) + +### Features + +* record first real-browser loopback verification of the generated artifact and fold that evidence into the open-source approval audit + +## [0.3.110](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.109...hsqlite-editor-v0.3.110) (2026-06-11) + +### Features + +* harden source, artifact, and runtime validation so SQL tab rename and close actions cannot regress to inherited generic button styling + +## [0.3.109](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.108...hsqlite-editor-v0.3.109) (2026-06-11) + +### Features + +* remove the residual button-style background from SQL tab rename and close actions so both controls render as clean inline icons inside the tab + +## [0.3.108](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.107...hsqlite-editor-v0.3.108) (2026-06-11) + +### Features + +* extend runtime smoke evidence to cover recent-database UI reopen, validating that clicking the rendered `Abrir` action reopens a handle-backed session through the visible list path + +## [0.3.107](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.106...hsqlite-editor-v0.3.107) (2026-06-11) + +### Features + +* extend runtime smoke evidence to cover SQL Map PNG export, validating that the real export path emits a downloadable `mapa-sql-der-*.png` artifact + +## [0.3.106](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.105...hsqlite-editor-v0.3.106) (2026-06-11) + +### Features + +* extend runtime smoke evidence to cover SQL Map copy behavior through the real action button, including clipboard writes and explicit status feedback + +## [0.3.105](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.104...hsqlite-editor-v0.3.105) (2026-06-11) + +### Features + +* fix the SQL Map paste delegation bug and extend runtime smoke evidence to cover normal paste plus clear-and-paste replacement into the active editor tab + +## [0.3.104](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.103...hsqlite-editor-v0.3.104) (2026-06-11) + +### Features + +* extend runtime smoke evidence to cover result-grid column resizing through the real resize handle, including persisted width updates and transient resize affordances + +## [0.3.103](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.102...hsqlite-editor-v0.3.103) (2026-06-11) + +### Features + +* extend runtime smoke evidence to cover query-history search and replay behavior, including filtered empty states and loading stored SQL back into the active tab + +## [0.3.102](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.101...hsqlite-editor-v0.3.102) (2026-06-11) + +### Features + +* extend runtime smoke evidence to cover SQL-tab lifecycle behavior, including new-tab activation and close confirmation with preview when a tab still contains SQL content + +## [0.3.101](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.100...hsqlite-editor-v0.3.101) (2026-06-11) + +### Features + +* extend runtime smoke evidence to cover schema-to-editor insertion, including field click insertion of `table.column` and Ctrl/Cmd+click insertion of the object name + +## [0.3.100](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.99...hsqlite-editor-v0.3.100) (2026-06-11) + +### Features + +* extend runtime smoke evidence to cover SQL Map field drag/drop relation creation, including source/target affordances and virtual-relationship creation through the UI interaction path + +## [0.3.99](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.98...hsqlite-editor-v0.3.99) (2026-06-11) + +### Features + +* extend runtime smoke evidence to cover result-grid column drag/drop reorder behavior, including persistence back into the active result set and real status feedback + +## [0.3.98](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.97...hsqlite-editor-v0.3.98) (2026-06-11) + +### Features + +* extend runtime smoke evidence to cover SQL-tab drag/drop reorder behavior and strengthen the fake DOM event/query surface needed to prove dynamic shell interactions + +## [0.3.97](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.96...hsqlite-editor-v0.3.97) (2026-06-11) + +### Features + +* extend runtime smoke evidence to cover local picker opening plus recent-handle reopen flows, including granted permission reset behavior and denied permission preservation/warning behavior + +## [0.3.96](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.95...hsqlite-editor-v0.3.96) (2026-06-11) + +### Features + +* remove the remaining inherited hover, focus, and active background styling from SQL tab rename and close controls so the actions render as clean inline icons + +## [0.3.95](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.94...hsqlite-editor-v0.3.95) (2026-06-11) + +### Features + +* harden SQL execution cancellation so interrupting the worker resolves cleanly without hanging the execution flow, then prove cancellation behavior in the runtime smoke and sync the maintainer docs/audit + +## [0.3.94](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.93...hsqlite-editor-v0.3.94) (2026-06-11) + +### Features + +* extend runtime smoke evidence to cover schema render/filter/reset behavior and multi-statement execution result-set handling, then sync the maintainer docs and approval audit to that stronger proof surface + +## [0.3.93](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.92...hsqlite-editor-v0.3.93) (2026-06-11) + +### Features + +* reconcile the operating context and approval audit with the stronger runtime-smoke evidence now in place, while explicitly preserving browser-level verification as the remaining major approval gap + +## [0.3.92](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.91...hsqlite-editor-v0.3.92) (2026-06-11) + +### Features + +* extend runtime smoke evidence to cover recent-database render/clear behavior and multi-version release-history badge expansion, and sync the maintainer docs/audit to that stronger proof surface + +## [0.3.91](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.90...hsqlite-editor-v0.3.91) (2026-06-10) + +### Features + +* remove the hover/focus background fill from SQL tab rename and close controls so the inline tab actions read as icon affordances instead of mini buttons + +## [0.3.90](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.89...hsqlite-editor-v0.3.90) (2026-06-10) + +### Features + +* register a backlog item for a QA-oriented synthetic data seeding workflow with per-column generation rules and bulk row-count control for performance testing + +## [0.3.89](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.88...hsqlite-editor-v0.3.89) (2026-06-10) + +### Features + +* keep the portable inline badge generic while documenting and shipping a `compact notification count` variant for tighter header-style notification badges + +## [0.3.88](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.87...hsqlite-editor-v0.3.88) (2026-06-10) + +### Features + +* register backlog items for virtual-FK orphan-data validation with diagnostic SQL output and for richer drag feedback while creating virtual relationships in the SQL Map + +## [0.3.87](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.86...hsqlite-editor-v0.3.87) (2026-06-10) + +### Features + +* reduce the Novidades count badge footprint and lift it slightly so the notification count reads more like a classic badge + +## [0.3.86](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.85...hsqlite-editor-v0.3.86) (2026-06-10) + +### Features + +* publish a detached portable inline-badge component folder with standalone CSS, JS, example HTML, and full markdown documentation for reuse in other projects + +## [0.3.85](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.84...hsqlite-editor-v0.3.85) (2026-06-10) + +### Features + +* extract a reusable inline badge component with `dot` and `count` modes plus configurable tones, and migrate the Novidades button to the numeric release-count variant + +## [0.3.84](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.83...hsqlite-editor-v0.3.84) (2026-06-10) + +### Features + +* bring the Novidades notification dot slightly closer to the label and enlarge it again for final visual evaluation + +## [0.3.83](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.82...hsqlite-editor-v0.3.83) (2026-06-10) + +### Features + +* slightly enlarge the Novidades notification dot now that the generic 16x16 override no longer distorts its real rendered size + +## [0.3.82](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.81...hsqlite-editor-v0.3.82) (2026-06-10) + +### Features + +* stop the generic hidden-icon button rule from forcing the Novidades badge back to 16x16 so the release indicator can finally render at its intended fixed size + +## [0.3.81](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.80...hsqlite-editor-v0.3.81) (2026-06-10) + +### Features + +* fix the Novidades badge sizing contract by rendering the indicator as a true fixed-size box instead of an inline text-sized span + +## [0.3.80](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.79...hsqlite-editor-v0.3.80) (2026-06-10) + +### Features + +* simplify the Novidades indicator into a static low-noise notification dot with dedicated spacing so the label remains visually dominant + +## [0.3.79](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.78...hsqlite-editor-v0.3.79) (2026-06-10) + +### Features + +* reduce the visual weight of the Novidades update badge so it reads as a subtle notification dot instead of a competing action chip + +## [0.3.78](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.77...hsqlite-editor-v0.3.78) (2026-06-10) + +### Features + +* remove the release badge overlay from the Novidades label and keep header actions from shrinking so the update indicator occupies its own layout space +## [0.3.77](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.76...hsqlite-editor-v0.3.77) (2026-06-10) + +### Features + +* reserve dedicated space for the release badge inside the Novidades button so the indicator no longer overlaps the label +## [0.3.76](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.75...hsqlite-editor-v0.3.76) (2026-06-10) + +### Features + +* move the release-update badge out of the label area and soften its pulse so the header indicator reads as a corner notification instead of competing with the Novidades text + +## [0.3.75](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.74...hsqlite-editor-v0.3.75) (2026-06-10) + +### Features + +* refine header-action visual hierarchy with a smaller animated release badge, normalized icon spacing, and move the recent-database clear action into the contextual recent-files modal +## [0.3.74](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.73...hsqlite-editor-v0.3.74) (2026-06-10) + +### Features + +* extend the runtime smoke harness to prove mutating SQL execution updates in-memory bytes and dirty-state signals, and update the maintainer guide plus approval audit to reflect that stronger mutation-flow evidence + +## [0.3.73](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.72...hsqlite-editor-v0.3.73) (2026-06-10) + +### Features + +* extend the runtime smoke harness to prove critical grid-state transitions after the refactor, and update the maintainer guide plus approval audit to reflect that stronger result-grid evidence + +## [0.3.72](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.71...hsqlite-editor-v0.3.72) (2026-06-10) + +### Features + +* extend the runtime smoke harness to prove settings-transfer export/import behavior, and update the maintainer guide plus approval audit to reflect that stronger configuration-portability evidence + +## [0.3.71](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.70...hsqlite-editor-v0.3.71) (2026-06-10) + +### Features + +* extend the runtime smoke harness to prove SQL Map join generation through declared and virtual relationships, and update the maintainer guide plus approval audit to reflect that stronger SQL Map evidence + +## [0.3.70](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.69...hsqlite-editor-v0.3.70) (2026-06-10) + +### Features + +* harden artifact validation so embedded release metadata, versioned offline help, and current release notes must stay synchronized across readable and minified standalone artifacts + +## [0.3.69](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.68...hsqlite-editor-v0.3.69) (2026-06-10) + +### Features + +* extend the runtime smoke harness to prove favorites persistence/render/clear behavior, and update the maintainer guide plus approval audit to reflect that stronger favorites-state evidence + +## [0.3.68](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.67...hsqlite-editor-v0.3.68) (2026-06-10) + +### Features + +* extend the runtime smoke harness to prove CSV/JSON result export behavior and update the maintainer guide plus approval audit to reflect that stronger export-flow evidence + +## [0.3.67](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.66...hsqlite-editor-v0.3.67) (2026-06-10) + +### Features + +* extend the runtime smoke harness to prove query-history persistence/render/clear behavior, and update the maintainer guide plus approval audit to reflect that stronger history-state evidence + +## [0.3.66](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.65...hsqlite-editor-v0.3.66) (2026-06-10) + +### Features + +* extend the runtime smoke harness to prove per-tab SQL/result isolation across tab switches, and update the maintainer guide plus approval audit to reflect that stronger tab state evidence + +## [0.3.65](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.64...hsqlite-editor-v0.3.65) (2026-06-10) + +### Features + +* remove leftover dead helpers from the migration path, including unused runtime changelog parsers and an obsolete SQLite file-validation wrapper, and make source validation reject those stale patterns if they reappear + +## [0.3.64](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.63...hsqlite-editor-v0.3.64) (2026-06-10) + +### Features + +* extend the runtime smoke harness to prove offline release metadata rendering from embedded bootstrap data, and update the maintainer guide plus approval audit to reflect that stronger release-trust evidence + +## [0.3.63](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.62...hsqlite-editor-v0.3.63) (2026-06-10) + +### Features + +* extend the runtime smoke harness to prove tab/grid state resets on valid DB replacement and state preservation on invalid replacement, and update the maintainer-facing audit/docs to reflect that stronger DB-switch evidence + +## [0.3.62](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.61...hsqlite-editor-v0.3.62) (2026-06-10) + +### Features + +* strengthen the repo-owned runtime smoke harness so it now verifies post-boot theme/session flows plus valid and invalid in-memory DB switching invariants, and document that stronger executable evidence in the maintainer guide and approval audit + +## [0.3.61](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.60...hsqlite-editor-v0.3.61) (2026-06-10) + +### Features + +* refresh the operating-context and approval-audit records to match the implemented standalone build/release pipeline, and fail source validation if repo-adjacent project thinking drifts back to stale migration-era assumptions or leaks machine-local paths + +## [0.3.60](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.59...hsqlite-editor-v0.3.60) (2026-06-10) + +### Features + +* enforce the post-boot shell-binding contract in source validation so future refactors cannot silently reintroduce early shortcut/theme/session wiring before `bootApp()` completes + +## [0.3.59](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.58...hsqlite-editor-v0.3.59) (2026-06-10) + +### Features + +* delay interactive shell bindings until `bootApp()` finishes so theme/session/shortcut controls cannot fire against partially initialized controllers during standalone artifact startup + +## [0.3.58](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.57...hsqlite-editor-v0.3.58) (2026-06-10) + +### Features + +* unify SQLite payload validation and runtime database creation for both file-based and generated-byte flows, so invalid candidates are rejected before any visible session reset and internal database creation follows one shared contract + +## [0.3.57](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.56...hsqlite-editor-v0.3.57) (2026-06-10) + +### Features + +* add repo-owned full release-gate commands for local and CI use, wire GitHub workflows to the CI variant, and document the difference between normal full validation and the stricter committed-artifact verification path + +## [0.3.56](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.55...hsqlite-editor-v0.3.56) (2026-06-10) + +### Features + +* document `appState` as the canonical runtime contract in the maintainer guide and harden source validation so legacy mirror-state globals or old sync-back patterns cannot silently re-enter the core state module + +## [0.3.55](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.54...hsqlite-editor-v0.3.55) (2026-06-10) + +### Features + +* move result-grid ownership under `appState.grid`, replace direct reads of mirrored grid globals across filtering, sorting, pagination, selection, resizing, export, SQL execution, and tab/result synchronization, and keep the generated standalone artifact passing runtime smoke after the state-contract shift + +## [0.3.54](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.53...hsqlite-editor-v0.3.54) (2026-06-10) + +### Features + +* move SQL tab ownership under `appState.tabs`, replace remaining direct reads of mirrored tab globals in tab lifecycle/render/storage flows, and route first-run rename, DB-session reset, and editor-change persistence through the centralized tabs contract + +## [0.3.53](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.52...hsqlite-editor-v0.3.53) (2026-06-10) + +### Features + +* move database session ownership under `appState`, replace remaining free-floating db-session globals with explicit selectors, and route SQL execution, dirty-state UI, SQL Map storage, and database export flows through the centralized session contract + +## [0.3.52](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.51...hsqlite-editor-v0.3.52) (2026-06-10) + +### Features + +* move release metadata, query history, and favorites under appState-backed ownership so these surfaces no longer depend on free-floating mirror variables, tightening source-of-truth integrity without a high-risk full-state rewrite + +## [0.3.51](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.50...hsqlite-editor-v0.3.51) (2026-06-10) + +### Features + +* add a repo-owned runtime smoke validator that executes the embedded boot payload and app code for both the readable and minified standalone artifacts, turning bootstrap readiness into a real release gate instead of a static-only assumption + +## [0.3.50](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.49...hsqlite-editor-v0.3.50) (2026-06-10) + +### Features + +* fail source and artifact validation when public docs or generated releases leak machine-local absolute paths, reinforcing open-source release hygiene as a hard gate instead of a reviewer-only warning + +## [0.3.49](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.48...hsqlite-editor-v0.3.49) (2026-06-10) + +### Features + +* add an explicit bootstrap surface with retry/failure locking, remove leaked machine-local paths from public docs, and make Pages/release workflows enforce the repo-owned validation and build pipeline before publish + +## [0.3.48](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.47...hsqlite-editor-v0.3.48) (2026-06-10) + +### Features + +* make source build ordering explicit through a repo-owned manifest and move remaining startup-side-effect bindings behind explicit init/bind functions so bootstrap discipline no longer depends on incidental file evaluation + +## [0.3.47](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.46...hsqlite-editor-v0.3.47) (2026-06-10) + +### Features + +* harden bootstrap sequencing so editor startup awaits runtime initialization and boot failures enter one explicit degraded state instead of leaving the shell partially initialized + +## [0.3.46](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.45...hsqlite-editor-v0.3.46) (2026-06-10) + +### Features + +* split query history, favorites, and settings-transfer behavior into focused modules so history and configuration workflows are reviewable without one mixed-responsibility file + +## [0.3.45](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.44...hsqlite-editor-v0.3.45) (2026-06-10) + +### Features + +* split the SQL Map subsystem into focused core, graph/layout, render, and interaction modules so the schema-map feature is reviewable without one giant mixed-responsibility file + +## [0.3.44](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.43...hsqlite-editor-v0.3.44) (2026-06-10) + +### Features + +* split the editor workflow into dedicated quick-history, file/drop workflow, and editor-action modules so editor behavior is reviewable without one mixed-responsibility file + +## [0.3.43](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.42...hsqlite-editor-v0.3.43) (2026-06-10) + +### Features + +* split the database session flow into dedicated recent-storage, session-runtime, and file-validation modules so database switching and file-opening responsibilities are reviewable in isolation + +## [0.3.42](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.41...hsqlite-editor-v0.3.42) (2026-06-10) + +### Features + +* split the SQL tab subsystem into dedicated storage, state/lifecycle, and render/interaction modules so tab behavior is reviewable without one mixed-responsibility source file + +## [0.3.41](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.40...hsqlite-editor-v0.3.41) (2026-06-10) + +### Features + +* split the oversized results UI into focused source modules for state/filtering, toolbar rendering, table interactions, and export flows while preserving the standalone offline artifact contract + +## [0.3.40](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.39...hsqlite-editor-v0.3.40) (2026-06-10) + +### Features + +* move shell bootstrap execution to the end of startup to stop temporal-dead-zone regressions, and replace runtime SQL splitter serialization with build-embedded shared worker source + +## [0.3.39](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.38...hsqlite-editor-v0.3.39) (2026-06-10) + +### Features + +* remove remaining in-place grid state mutations from the results UI and extend source validation so selection, sorting, and column-width state must keep flowing through immutable updates + +## [0.3.38](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.37...hsqlite-editor-v0.3.38) (2026-06-10) + +### Features + +* group UI event wiring by feature area so startup bindings are reviewable by domain instead of one long top-level block + +## [0.3.37](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.36...hsqlite-editor-v0.3.37) (2026-06-10) + +### Features + +* enforce a source-level guardrail against direct mutation of critical runtime state outside the core state module and route dirty-session updates through the central db-session setter + +## [0.3.36](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.35...hsqlite-editor-v0.3.36) (2026-06-10) + +### Features + +* turn inline JavaScript syntax validation into a built-in artifact gate so readable and minified standalone releases fail before shipping malformed embedded scripts + +## [0.3.35](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.34...hsqlite-editor-v0.3.35) (2026-06-10) + +### Features + +* fix invalid embedded SQL error regex literals, harden tab and db-session state updates, and prevent the generated standalone artifact from shipping a broken inline script + +## [0.3.34](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.33...hsqlite-editor-v0.3.34) (2026-06-10) + +### Features + +* centralize active result-set hydration/persistence through shared state helpers and remove stale release literals from the source template and operating context + +## [0.3.33](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.32...hsqlite-editor-v0.3.33) (2026-06-10) + +### Features + +* remove obsolete sample-database style residue and block public release unless source, readable artifact, and minified artifact validations all pass + +## [0.3.32](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.31...hsqlite-editor-v0.3.32) (2026-06-10) + +### Features + +* add repo-owned source-surface validation and remove stale sample-database references from maintainer-facing docs and styles + +## [0.3.31](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.30...hsqlite-editor-v0.3.31) (2026-06-10) + +### Features + +* replace the last runtime monolith with dedicated DOM lookup and runtime bootstrap modules, eliminating src/app/50-runtime.js + +## [0.3.30](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.29...hsqlite-editor-v0.3.30) (2026-06-10) + +### Features + +* extract shared runtime helpers for modal control, result-state ownership, shell dirty-state, and horizontal result scrolling into a dedicated app module + +## [0.3.29](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.28...hsqlite-editor-v0.3.29) (2026-06-10) + +### Features + +* extract the SQL Map subsystem into a dedicated app module, removing schema graph, drag, relation, and export logic from the main runtime + +## [0.3.28](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.27...hsqlite-editor-v0.3.28) (2026-06-10) + +### Features + +* add a repo-owned minified release artifact flow with dedicated build and post-minification validation commands + +## [0.3.27](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.26...hsqlite-editor-v0.3.27) (2026-06-10) + +### Features + +* extract SQL find/replace state, highlighting, navigation, and replacement flows into a dedicated app module + +## [0.3.26](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.25...hsqlite-editor-v0.3.26) (2026-06-10) + +### Features + +* extract editor runtime bootstrap, SQL error guidance, toast feedback, and SQL busy-state handling into a dedicated app module + +## [0.3.25](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.24...hsqlite-editor-v0.3.25) (2026-06-10) + +### Features + +* extract editor-local workflow including quick history, SQL file loading, drag-and-drop, resize, and editor action shortcuts into a dedicated app module + +## [0.3.24](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.23...hsqlite-editor-v0.3.24) (2026-06-10) + +### Features + +* extract database session switching, recent-file tracking, handle persistence, file validation, and picker flows into a dedicated app module + +## [0.3.23](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.22...hsqlite-editor-v0.3.23) (2026-06-10) + +### Features + +* extract SQL tab lifecycle, persistence, rename, overflow, and close flows into a dedicated app module + +## [0.3.22](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.21...hsqlite-editor-v0.3.22) (2026-06-10) + +### Features + +* extract shell offline/schema/status boot helpers into a dedicated app module and lock the release plan around pre- and post-minification validation + +## [0.3.21](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.20...hsqlite-editor-v0.3.21) (2026-06-10) + +### Features + +* extract keyboard shortcuts and shell menu wiring into a dedicated app module to further reduce runtime sprawl + +## [0.3.20](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.19...hsqlite-editor-v0.3.20) (2026-06-10) + +### Features + +* extract theme, session persistence, first-run preferences, and tab-preset entrypoints into a dedicated app preferences module + +## [0.3.19](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.18...hsqlite-editor-v0.3.19) (2026-06-10) + +### Features + +* extract query history, favorites, and settings transfer flows into a dedicated app module to keep the main runtime focused on orchestration + +## [0.3.18](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.17...hsqlite-editor-v0.3.18) (2026-06-10) + +### Features + +* extract release metadata parsing, normalization, badge handling, and release-notes modal preparation into a dedicated app module + +## [0.3.17](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.16...hsqlite-editor-v0.3.17) (2026-06-10) + +### Features + +* formalize core app contracts for release metadata, database sessions, and tab state, and document the layered source architecture for maintainers + +## [0.3.16](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.15...hsqlite-editor-v0.3.16) (2026-06-10) + +### Features + +* replace the last monolithic UI event file with explicit shared helpers and feature-level binding modules + +## [0.3.15](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.14...hsqlite-editor-v0.3.15) (2026-06-10) + +### Features + +* extract database creation, save, and schema-export actions into a dedicated UI module so the remaining event file stays focused on wiring + +## [0.3.14](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.13...hsqlite-editor-v0.3.14) (2026-06-10) + +### Features + +* extract editor autocomplete parsing, suggestion rendering, and keyboard navigation into a dedicated UI module + +## [0.3.13](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.12...hsqlite-editor-v0.3.13) (2026-06-10) + +### Features + +* extract result-grid rendering, interactions, and export flow into a dedicated UI module to further break down the monolithic event layer + +## [0.3.12](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.11...hsqlite-editor-v0.3.12) (2026-06-10) + +### Features + +* extract schema loading, filtering, and rendering into a dedicated UI module to keep the standalone build behavior while shrinking the monolithic event file + +## [0.3.11](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.10...hsqlite-editor-v0.3.11) (2026-06-10) + +### Features + +* remove the per-tab submenu pattern and keep SQL tab actions on direct inline rename plus close controls + +## [0.3.10](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.9...hsqlite-editor-v0.3.10) (2026-06-10) + +### Features + +* reduce duplicated grid authority by keeping per-tab result ownership in result sets instead of mirrored active-grid snapshots + +## [0.3.9](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.8...hsqlite-editor-v0.3.9) (2026-06-10) + +### Features + +* simplify SQL tabs with direct rename actions, remove the hidden sample-database surface, and replace string-evaluated SQL splitting with one shared implementation + +## [0.3.8](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.7...hsqlite-editor-v0.3.8) (2026-06-10) + +### Features + +* tone down SQL tab actions so the close control stays primary while the overflow menu appears only on hover or focus + +## [0.3.7](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.6...hsqlite-editor-v0.3.7) (2026-06-10) + +### Features + +* rewrite SQL tabs into a workbench rail with separate utility rail, tab menu, and explicit overflow entrypoint + +## [0.3.6](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.5...hsqlite-editor-v0.3.6) (2026-06-10) + +### Features + +* reduce tab action controls to compact inline icons and remove the oversized protruding action styling + +## [0.3.5](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.4...hsqlite-editor-v0.3.5) (2026-06-10) + +### Features + +* clean release-note links in the in-app modal and wrap long entries without layout overflow + +## [0.3.4](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.3...hsqlite-editor-v0.3.4) (2026-06-10) + +### Features + +* move tab rename and close actions inside each tab pill and reveal them on hover or focus + +## [0.3.3](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.2...hsqlite-editor-v0.3.3) (2026-06-09) + +### Features + +* refactor source into a generated standalone artifact workflow with embedded offline runtimes +* pin vendored dependencies with manifest checksums and repo-owned update automation +* add repo-owned patch version bump command and enforce manifest/package version sync + ## [0.3.2](https://github.com/helbertm/hSQLite-Editor/compare/hsqlite-editor-v0.3.1...hsqlite-editor-v0.3.2) (2026-05-27) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..67c6f73 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,41 @@ +# Code of Conduct + +## Our pledge + +We pledge to make participation in hSQLite Editor a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socioeconomic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. + +## Our standards + +Examples of behavior that contributes to a positive environment include: + +- Demonstrating empathy and kindness toward other people +- Respecting differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility, apologizing to those affected by mistakes, and learning from the experience +- Focusing on what is best for the community and the project + +Examples of unacceptable behavior include: + +- Sexualized language or imagery, sexual attention, or advances of any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing another person's private information without explicit permission +- Other conduct that could reasonably be considered inappropriate in a professional setting + +## Enforcement responsibilities + +Project maintainers are responsible for clarifying and enforcing acceptable behavior. They may remove, edit, or reject comments, commits, code, issues, and other contributions that do not align with this Code of Conduct, and will communicate moderation reasons when appropriate. + +## Scope + +This Code of Conduct applies within all project spaces and when an individual officially represents the project in public spaces. + +## Enforcement + +Report abusive, harassing, or otherwise unacceptable behavior privately through the repository owner's GitHub profile contact options. Reports will be reviewed promptly and fairly. Maintainers must respect the privacy and security of reporters. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant, version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct.html). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..70ac0d0 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,60 @@ +# Contributing to hSQLite Editor + +Thank you for improving hSQLite Editor. Contributions are reviewed for product value, maintainability, accessibility, privacy, and preservation of the standalone offline artifact. + +## Before you start + +- Use GitHub Discussions or an issue for broad design changes before investing in implementation. +- Use the security reporting process in [SECURITY.md](SECURITY.md) for vulnerabilities. Do not open a public security issue. +- Keep changes focused. Unrelated refactors make review and regression analysis harder. +- Do not edit generated `index.html` or `dist/` artifacts by hand. + +## Development setup + +Requirements: + +- Node.js 20 or newer +- A current Chromium-based browser for automated browser checks +- Safari on macOS for the native `file://` release smoke test + +Run the repository-owned checks: + +```sh +npm run validate:source +npm run test:contract +npm run build +npm run validate:artifact +npm run validate:full +``` + +Use `npm run serve:artifact` to inspect the generated application over loopback. The production contract remains direct `file://` use of the standalone HTML artifact. +The validation layers and their runtime boundaries are documented in [docs/validation.md](docs/validation.md). + +## Change requirements + +- Add or update tests for changed behavior. +- Keep user-facing copy in the locale catalogs. Do not introduce hard-coded interface strings. +- Preserve keyboard operation and visible focus for every interactive workflow. +- Meet WCAG 2.2 Level AA for changed UI. +- Update `docs/architecture.md` when ownership or runtime boundaries change. +- Update `design_system.md` when a visible pattern or token changes. +- Update `security_posture.md` when security assumptions or controls change. +- Add a `CHANGELOG.md` entry through the release-please workflow; do not manually invent release versions. + +## Commit and pull request conventions + +Use [Conventional Commits](https://www.conventionalcommits.org/): + +```text +feat: add locale-aware result formatting +fix(grid): preserve focus after sorting +docs: clarify offline release verification +``` + +Pull requests must explain the problem, the chosen approach, verification performed, accessibility impact, localization impact, and any residual risk. Maintainers may request a smaller change when a proposal combines independent concerns. + +## Review standard + +Passing automation is necessary but not sufficient. Review also considers data integrity, browser compatibility, error recovery, local-first privacy, performance on large SQLite files, and whether the change keeps the one-file release reproducible. + +By participating, you agree to follow [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md). diff --git a/GOVERNANCE.md b/GOVERNANCE.md new file mode 100644 index 0000000..8a5a884 --- /dev/null +++ b/GOVERNANCE.md @@ -0,0 +1,24 @@ +# Governance + +hSQLite Editor uses a maintainer-led governance model. + +## Roles + +- **Maintainers** set product direction, review and merge changes, manage releases, moderate community spaces, and handle security reports. +- **Contributors** propose changes, participate in review, improve documentation, and help other users. + +The current repository owner is the initial maintainer. Maintainers may invite contributors with a sustained record of sound technical judgment, constructive review, and responsible community participation. + +## Decisions + +Routine decisions are made through issue and pull request review. Material changes to architecture, data handling, compatibility, accessibility, localization, or release trust require a written rationale and explicit maintainer approval. + +When consensus is not reached, maintainers decide based on user impact, project scope, maintenance cost, evidence, and reversibility. Decisions may be revisited when new evidence appears. + +## Releases and security + +Only maintainers may publish releases. A release must pass the repository-owned verification suite and the release checklist in `docs/releasing.md`. Security handling follows [SECURITY.md](SECURITY.md). + +## Changes to governance + +Governance changes use the same pull request process as code and require explicit maintainer approval. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..da5109b --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 hSQLite Editor contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..d36b8fe --- /dev/null +++ b/README.md @@ -0,0 +1,120 @@ +# hSQLite Editor + +[![Deploy GitHub Pages](https://github.com/helbertm/hSQLite-Editor/actions/workflows/pages.yml/badge.svg)](https://github.com/helbertm/hSQLite-Editor/actions/workflows/pages.yml) +[![Quality Gate](https://github.com/helbertm/hSQLite-Editor/actions/workflows/quality.yml/badge.svg)](https://github.com/helbertm/hSQLite-Editor/actions/workflows/quality.yml) +[![Browser Quality](https://github.com/helbertm/hSQLite-Editor/actions/workflows/browser-quality.yml/badge.svg)](https://github.com/helbertm/hSQLite-Editor/actions/workflows/browser-quality.yml) +[![CodeQL](https://github.com/helbertm/hSQLite-Editor/actions/workflows/codeql.yml/badge.svg)](https://github.com/helbertm/hSQLite-Editor/actions/workflows/codeql.yml) +[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) + +hSQLite Editor is a local-first SQLite workspace that runs entirely in the browser. Open a database, write and execute SQL, inspect the schema, explore relationships, edit multiple query tabs, and export results without sending database contents to an application server. + +The product is distributed as one standalone `index.html` artifact and is offline-capable in `file://` mode. Runtime dependencies, SQLite WebAssembly, styles, and application code are embedded in that file. + +## Try it + +- [Open hSQLite Editor](https://helbertm.github.io/hSQLite-Editor/) +- Download the versioned standalone HTML file from the latest [GitHub release](https://github.com/helbertm/hSQLite-Editor/releases/latest) for direct offline use. + +## Capabilities + +- Open, create, inspect, modify, and save SQLite databases locally. +- Execute multiple SQL statements in an isolated Web Worker with cancellation and elapsed-time feedback. +- Use independent SQL tabs, query history, favorites, file import/export, and keyboard shortcuts. +- Inspect schema objects and insert table or column identifiers into the editor. +- Sort, filter, paginate, select, freeze, move, resize, and export result columns. +- Build SQL visually from declared and session-only virtual relationships in SQL Map. +- Validate virtual-relationship orphan data before accepting a relationship. +- Generate synthetic table data for local QA with transaction rollback and cancellation safety. +- Persist optional session data in browser storage and transfer selected settings as JSON. +- Switch among `en-US`, `pt-BR`, and `es-ES` interface locales. +- Use primary workflows with a keyboard and visible focus under the WCAG 2.2 AA accessibility target. + +## Privacy and trust boundary + +hSQLite Editor has no application backend and does not intentionally upload databases, queries, history, or settings. Files and browser storage remain on the device unless the user explicitly exports or shares them. + +The browser, browser extensions, operating system, downloaded artifact, and files selected by the user remain outside the project's trust boundary. Browser storage is not an encrypted secrets vault. The complete localStorage, IndexedDB, recent-file metadata, clearing, and permission-revocation inventory is in [docs/privacy.md](docs/privacy.md). See [SECURITY.md](SECURITY.md) and [security_posture.md](security_posture.md). + +## Browser support + +Automated browser validation targets current Chromium releases. The release checklist also requires host-native Chromium and Safari smoke tests against the final standalone artifact through `file://`. Browser-managed file handles and clipboard behavior vary by browser and security context; fallback file inputs and explicit export flows remain available. + +## Development + +Requirements: + +- Node.js 20 or newer +- A current browser + +Clone the repository and run: + +```sh +npm run validate:full +``` + +This command runs the static-policy, deterministic contract, artifact/runtime, and approval layers in sequence against both readable and minified artifacts. Browser, security-update, and host-native layers stay explicit because they require different runtimes. See [docs/validation.md](docs/validation.md) for the complete command matrix. + +Useful focused commands: + +```sh +npm run build +npm run stage:linux +npm run serve:artifact +npm run validate:static +npm run test:contract +npm run validate:source +npm run validate:i18n +npm run validate:accessibility +npm run validate:privacy +npm run validate:artifact +npm run validate:artifact:structure +npm run validate:runtime +npm run validate:runtime:features +npm run validate:release +npm run validate:linux +npm run validate:native:chromium +npm run validate:approval +npm run validate:dependencies +npm run quality:docker +npm run quality:security:docker +``` + +Do not edit generated `index.html` or `dist/` artifacts manually. Change source under `src/`, then rebuild. + +## Architecture + +The project is a modular browser monolith: + +- `src/core/` owns domain contracts, pure helpers, runtime configuration, and authoritative application state. +- `src/ports/` isolates browser storage, file, clipboard/download, and SQL worker adapters. +- `src/capabilities/` implements product workflows. +- `src/ui/` renders state and binds interaction. +- `src/styles/` contains the design system and responsive feature layouts. +- `scripts/` provides deterministic build, release, and verification commands. +- `vendor/` contains pinned runtime assets with SHA-256 provenance. + +The build combines these sources into the standalone artifact without requiring runtime network access. See [docs/architecture.md](docs/architecture.md) for invariants and change policy. + +## Localization and accessibility + +`en-US` is the fallback locale; the workspace and advanced flows are available in `en-US`, `pt-BR`, and `es-ES`. User-facing text belongs in the central catalogs, and locale-sensitive formatting uses shared `Intl` helpers. See [docs/localization.md](docs/localization.md). + +The project targets WCAG 2.2 Level AA. Changes to visible behavior must preserve programmatic names, keyboard operation, focus management, contrast, zoom/reflow behavior, and announcements. See [docs/accessibility.md](docs/accessibility.md). + +## Dependencies and releases + +SQL.js runtime files are vendored with exact upstream URLs, versions, licenses, and SHA-256 hashes in `vendor/manifest.json`. The CodeMirror 6 editor is built from exact locked npm development dependencies because browsers receive the compiled inline bundle rather than npm packages. Every package in that shipped bundle is recorded in `runtime-components.json`; generation requires the esbuild input graph and lockfile dependency closure to agree. The SPDX SBOM marks both forms as shipped runtime components and also inventories development/release dependencies. [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md) identifies included software. + +Readable and minified artifacts are validated independently. Release automation uses Conventional Commits and release-please. Maintainer steps and GitHub-side controls are documented in [docs/releasing.md](docs/releasing.md). + +Linux distributors can consume a deterministic filesystem stage without introducing a second runtime or file-association contract. See [docs/linux-packaging.md](docs/linux-packaging.md). + +## Contributing + +Read [CONTRIBUTING.md](CONTRIBUTING.md), [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md), and [GOVERNANCE.md](GOVERNANCE.md) before contributing. Use [GitHub Discussions](https://github.com/helbertm/hSQLite-Editor/discussions) for usage questions or broad design proposals and the issue forms for reproducible defects and scoped feature requests. + +Report vulnerabilities privately as described in [SECURITY.md](SECURITY.md). + +## License + +hSQLite Editor is available under the [MIT License](LICENSE). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..3f0cd30 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,19 @@ +# Security Policy + +## Supported versions + +Security fixes are provided for the latest published release. Older standalone artifacts should be replaced with the current release. + +## Reporting a vulnerability + +Do not disclose suspected vulnerabilities in public issues, pull requests, or discussions. + +Use [GitHub Private Vulnerability Reporting](https://github.com/helbertm/hSQLite-Editor/security/advisories/new). Include affected versions, reproduction steps, impact, and any proposed remediation. Remove personal, confidential, or production database content from reports. + +You should receive an acknowledgement within seven days. The maintainers will assess severity, coordinate remediation, and publish an advisory when affected users need to act. Disclosure timing will be agreed with the reporter when practical. + +## Security model + +hSQLite Editor is a client-side, local-first application. It does not require a backend and does not intentionally upload database contents. Browser APIs, extensions, the host operating system, and files opened by the user remain outside the project's trust boundary. + +The standalone artifact embeds its runtime dependencies. Releases are accepted only after source, artifact, vendor-integrity, dependency-advisory, and runtime validation. See [security_posture.md](security_posture.md) for current controls and limits, and [docs/privacy.md](docs/privacy.md) for the exact local data inventory and removal steps. diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 0000000..acef7ba --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,13 @@ +# Support + +Use [GitHub Discussions](https://github.com/helbertm/hSQLite-Editor/discussions) for usage questions and design discussion. Use [GitHub Issues](https://github.com/helbertm/hSQLite-Editor/issues) for reproducible defects and scoped feature requests. + +Before filing an issue: + +- Confirm the problem on the latest release. +- Remove confidential data and provide a minimal synthetic database when reproduction requires a file. +- Include browser name/version, operating system, whether the artifact was opened with `file://` or loopback HTTP, and exact reproduction steps. + +Security reports belong in the private process described by [SECURITY.md](SECURITY.md). + +Support is community-provided on a best-effort basis. No response-time or compatibility SLA is offered. diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md new file mode 100644 index 0000000..4788aa1 --- /dev/null +++ b/THIRD_PARTY_NOTICES.md @@ -0,0 +1,12 @@ +# Third-Party Notices + +hSQLite Editor includes the following software in its generated standalone artifact: + +| Component | Version | License | Upstream | +| --- | --- | --- | --- | +| CodeMirror 6 editor bundle | Exact packages in `runtime-components.json` | MIT | https://codemirror.net/ | +| sql.js | 1.14.1 | MIT | https://github.com/sql-js/sql.js | + +Exact bundled npm components are recorded in `runtime-components.json`; vendored files and SHA-256 digests are recorded in `vendor/manifest.json`. The build and validation gates reject stale provenance before producing a release artifact. + +Third-party names and trademarks belong to their respective owners. Their licenses apply to their components; the hSQLite Editor project is licensed under MIT. diff --git a/design_system.md b/design_system.md index 2b3c449..41b17b3 100644 --- a/design_system.md +++ b/design_system.md @@ -18,8 +18,12 @@ Rule: ## Typography - Keep current sans stack for now. -- Use only 4 semantic sizes: `12`, `14`, `16`, `20`. -- Titles and section labels must follow semantic role, not ad hoc sizing. +- Core semantic sizes are `12`, `14`, `16`, and `20` px. +- Dense operational metadata may use `9`, `10`, `11`, or `13` px when the same role is consistent across its component family. +- Section and modal headings may use `17`, `18`, `22`, or `24` px. The boot/offline display heading may use `34` px on large screens and `22` px at constrained widths. +- `font-size: 0` is permitted only on a wrapper that visually suppresses whitespace or a redundant text slot; accessible text must remain available through semantics. +- Titles and section labels follow semantic role, not ad hoc per-instance sizing. +- Font sizes do not scale continuously with viewport width. Responsive typography uses explicit breakpoint changes. ## Spacing Scale - Spacing tokens: `4, 8, 12, 16, 20, 24`. @@ -46,7 +50,12 @@ Rule: - Runtime switch implementation classes: `ui-switch`, `ui-switch-segmented`, `ui-switch-option`, `ui-switch-thumb`. - Menu triggers implemented with `summary` must match button focus, hover, height, border, and radius behavior. - SQL tabs follow the accessible tab pattern: tablist, tab roles, roving `tabindex`, ArrowLeft/ArrowRight navigation, Home/End navigation, active-tab scroll-into-view, and overflow affordance only when content exceeds the strip. +- SQL tabs use the `workbench rail` model: label-first tab hit area plus a distinct utility rail. +- In the workbench rail, `close` and `rename` are the only inline utilities. `rename` remains secondary to `close`. +- `rename` is exposed by the inline pencil action, `F2`, and double click on the title. Tabs must not rely on per-tab submenus for their primary editing actions, and the workbench rail must not render a `...` per-tab action menu. - Tab close/rename affordances must remain discoverable on keyboard and touch. Hover may emphasize controls, but must not be the only way to discover the capability. +- SQL tab utility rails must not be implemented as absolute overlays with compensating label padding. +- When the tab strip overflows, it must keep horizontal scroll plus an explicit overflow entrypoint for hidden tabs. - Empty states in the primary workflow are operational and low-motion. Didactic personality belongs in optional help/onboarding surfaces. - Result toolbars must expose labels for compact/icon controls and keep pagination, filtering, sort reset, selection reset, and freeze reset visually distinct but consistent. @@ -79,9 +88,13 @@ Rule: - At constrained widths, preserve visibility of SQL tabs, Run, and database-open flow before secondary utilities. - Prefer adaptive grouping and overflow menus over uncontrolled toolbar wrapping. - Breakpoint contracts: +- `<= 1100px`: result and utility groups may reduce density before the primary workspace collapses. +- `<= 980px`: SQL Map adapts its graph and inspector composition. - `> 920px`: schema and editor render as two columns. - `<= 920px`: schema defaults to collapsed when no saved user preference exists; F4/rail restores it. +- `<= 760px`: session/settings controls may recompose before the main mobile threshold. - `<= 720px`: header actions recompose into a grid, database status occupies its own row, editor actions prioritize Run + SQL file actions + overflow trigger. +- `<= 640px`: first-run and settings surfaces use their narrow composition. - `<= 560px`: result toolbar becomes single-column; tab titles shrink before controls disappear. ## Table And Result Semantics @@ -105,15 +118,51 @@ Rule: - Always expose explicit controls to clear/reset stored UI state. - For future release: support selective export/import of browser-stored data and preferences with clear scope labels and conflict strategy. -## Deferred Features (Backlog) +## Feature Status - Favorite instructions UX: - Save from history to favorites. - Favorites list with search/filter and quick load to editor. - Settings portability UX: - Export selected data scopes (favorites, history, theme, session, SQL tabs). - Import with preview of selected scopes and merge/replace choice. +- Implemented SQL Map gesture UX: +- Virtual-FK creation by drag-and-drop should feel materially dragged, with a floating relationship affordance that follows the pointer until drop/cancel. +- The gesture must keep target discovery readable and must not rely on heavy animation. +- Implemented SQL Map data integrity guardrail: +- Virtual FKs are UI-level relationships, but creation should still validate live data compatibility. +- If orphan rows exist on either side of the intended join, the UI should block creation and offer a generated SQL diagnostic that reveals the orphan records. +- Implemented QA data seeding UX: +- Provide a guided table-seeding flow that maps columns and lets the user configure deterministic or random generation rules per field before bulk insertion. +- The workflow should keep PK generation automatic by default, expose type-aware strategies for numeric/text/date-like fields, and make the target row count explicit before execution. +- The surface should communicate that this is a QA/performance utility, not a primary production workflow. ## Acceptance Gates (P0/P1/P2) - P0: interaction trust (shortcuts, focus, dialogs, keyboard table operations). - P1: shell hierarchy and responsive density. - P2: durable systemization (tokens, components, command palette/help, motion standards). +# Localization Contract + +- Supported locale tags are `en-US`, `pt-BR`, and `es-ES`; `en-US` is the final fallback. +- Visible copy, accessible names, status messages, validation feedback, empty states, and help content are localization surfaces. +- Use stable catalog keys and shared `Intl` formatting helpers. Do not format dates, numbers, relative time, or collation directly inside feature modules. +- Controls and layouts must tolerate at least 35% text expansion without clipping, overlap, or horizontal page scrolling. +- Keep SQL, filenames, user data, and database identifiers unchanged unless presentation explicitly requires locale formatting. +- The language selector is an option menu, not a decorative segmented control, and displays each language in its native name. + +# Accessibility Contract + +- Target WCAG 2.2 Level AA. +- Every input and control has a programmatic accessible name; placeholders never act as labels. +- Every pointer interaction has a keyboard equivalent or an adjacent accessible command surface. +- Result-table headers support keyboard sorting, freezing, moving, and resizing. Rows use roving focus, arrow navigation, and Space selection. +- Dialogs provide a name, modal semantics, focus containment, Escape/cancel behavior, and focus restoration. +- Dynamic status and errors use live regions without stealing focus. +- Focus indicators use `--ring`, remain visible in both themes, and are not removed without an equivalent replacement. +- Color is never the sole indicator of state, severity, selection, or relationship compatibility. + +# Responsive Content Rules + +- Fixed-format controls use stable dimensions, but user-facing labels may wrap when the translated text requires it. +- Header actions may reflow into additional rows; they must never overlap the database status or locale selector. +- Modal content must remain usable at 320 CSS px width and 400% browser zoom. +- Tables may scroll horizontally inside their own region; the document itself must not gain incoherent horizontal overflow. diff --git a/docs/accessibility.md b/docs/accessibility.md new file mode 100644 index 0000000..33c8943 --- /dev/null +++ b/docs/accessibility.md @@ -0,0 +1,28 @@ +# Accessibility + +## Target + +hSQLite Editor targets WCAG 2.2 Level AA for the latest release. Accessibility is a release property, not an optional enhancement. + +## Interaction contract + +- Every primary workflow must be operable with a keyboard. +- Focus must be visible and move predictably when dialogs open, close, or update. +- Controls require programmatic names; placeholders are not labels. +- Dialogs require an accessible name, appropriate description, focus containment, and focus restoration. +- Status and error feedback must be exposed without moving focus unnecessarily. +- SQL tabs keep form controls outside `role="tab"`. F2 starts an inline rename, Enter commits, Escape cancels, and both paths restore focus to the same tab. Rename and close commands for the active tab live outside the tablist and remain keyboard reachable. +- Error toasts use atomic assertive announcements; informational toasts use atomic polite announcements. Toasts never take focus, and their close buttons have localized accessible names. +- Results-grid sorting, row selection, current-row movement, and column operations require keyboard equivalents or an accessible command surface. +- SQL Map table and field selectors expose names derived from the visible database identifiers. Relationship controls support Enter and Space, preserve pressed state while a source is selected, and announce source, cancellation, blocked validation, and completion within the open dialog. +- Foreign-key direction help follows the active `en-US`, `pt-BR`, or `es-ES` locale and opens official documentation in a separate browser context. +- Color cannot be the only carrier of meaning. Text and controls must meet WCAG AA contrast. +- The active locale must be reflected in ``. + +## Verification + +Run static source checks, automated browser accessibility checks in every supported locale, keyboard workflow tests, zoom/reflow checks, and native Safari smoke on the final `file://` artifact. Automated checks cannot prove screen-reader usability; release review includes manual keyboard and assistive-technology spot checks for changed workflows. + +The browser matrix also checks SQL-tab rename and command focus behavior and runs axe against the populated tablist. The populated SQL Map scenario checks accessible names against real table and field identifiers, validates focus order and keyboard relationship creation, verifies blocked-state behavior, inspects the browser accessibility tree, and runs axe while the dialog is open. + +Known limitations and remediation status belong in `security_posture.md` or a tracked public issue, never only in local agent notes. diff --git a/docs/adr/0001-codemirror-6-editor-runtime.md b/docs/adr/0001-codemirror-6-editor-runtime.md new file mode 100644 index 0000000..b342fd1 --- /dev/null +++ b/docs/adr/0001-codemirror-6-editor-runtime.md @@ -0,0 +1,42 @@ +# ADR 0001: CodeMirror 6 Editor Runtime + +- Status: Accepted +- Date: 2026-07-18 +- Decision owners: BurleMarx architecture gate and project maintainers + +## Context + +hSQLite Editor must ship as one offline-capable HTML file that opens through `file://`. The existing SQL editor uses the legacy CodeMirror 5 global API, vendored scripts, vendored themes, and direct API calls spread across editor, search, autocomplete, shortcut, preference, and test code. + +CodeMirror 6 is distributed as ECMAScript modules and requires a build step. Loading modules, import maps, CDN assets, or additional local files at runtime would violate the standalone artifact contract. + +## Decision + +Use pinned CodeMirror 6 packages and SQL language support at build time. Bundle one repo-owned editor adapter as an IIFE and inline it before the application scripts in both readable and release artifacts. + +Only `src/editor/codemirror6-adapter.mjs` may import CodeMirror or Lezer packages. Application capabilities depend on the adapter contract for creation, value, selection, cursor, replacement, search highlighting, theme, accessibility attributes, focus, geometry, and keyboard/event integration. + +The editor view is a runtime projection. `appState` and SQL-tab state remain authoritative application data. + +## Consequences + +- Builds require the pinned npm dependency tree and esbuild. +- The exact npm packages included in the editor bundle are recorded in `runtime-components.json` and marked as shipped runtime dependencies in the SPDX SBOM. +- The final artifact remains one HTML file with no runtime network or module loading. +- CodeMirror 5 assets, package metadata, selectors, test doubles, and compatibility branches are removed in the same migration. +- The broader application module-graph migration remains Item 9 and is not part of this decision. + +## Rejected Alternatives + +- Shipping CodeMirror 5 and 6 together. +- Loading CodeMirror from a CDN, dynamic import, import map, or adjacent runtime files. +- Importing CodeMirror directly from feature modules. +- Preserving a general CodeMirror 5 compatibility facade. +- Creating a second distribution artifact. + +## Verification + +- Unit contracts cover adapter value, selection, replacement, search, and event behavior. +- Artifact validation rejects CodeMirror 5 residue, external runtime URLs, source maps, `eval`, and dynamic code construction. +- Browser validation covers localized editor naming, keyboard input, selection, find/replace, autocomplete, quick history, themes, reduced motion, mobile layout, and 200% equivalent reflow. +- Release validation confirms the exact artifact is offline under Chromium and native Safari checks. diff --git a/docs/adr/0002-esm-application-module-graph.md b/docs/adr/0002-esm-application-module-graph.md new file mode 100644 index 0000000..a98a96f --- /dev/null +++ b/docs/adr/0002-esm-application-module-graph.md @@ -0,0 +1,56 @@ +# ADR 0002: ESM Application Module Graph + +- Status: Accepted +- Date: 2026-07-18 +- Decision owners: BurleMarx architecture gate and project maintainers + +## Context + +hSQLite Editor currently builds its application by concatenating 59 classic-script fragments in a manually maintained order. Those fragments share one broad lexical scope, so dependencies are implicit, cycles are hidden, and moving a file can change runtime behavior without an import or export contract. + +The application must continue to ship as one offline-capable HTML file that opens through `file://`. A source-level module graph therefore cannot become a runtime module loader, import map, network dependency, or multi-file distribution. + +## Decision + +Use native ECMAScript modules as the application source format and esbuild as the build-time linker. `src/app.mjs` is the sole application entry point. The build emits one browser IIFE and inlines it into the existing standalone HTML artifact after the vendored SQLite runtime, the editor adapter, and boot metadata. + +Every durable dependency crosses a file boundary through an explicit import and export. The target ownership direction is: + +`application entry/kernel -> UI surfaces -> capabilities -> core contracts -> browser ports` + +Cycles must be removed through narrower contracts or dependency inversion. A shared event bus, service locator, framework migration, API layer, or second distribution artifact is not part of this decision. + +`appState` remains the sole authoritative application state. Domain state accessors may be split into narrower modules, but they must operate on that same object. Browser-specific effects remain in ports. DOM references are exported from surface-owned registries. Ephemeral editor, worker, pointer, and rendering caches remain feature-owned runtime data rather than competing state. + +## Build And Test Boundary + +The production artifact does not expose module internals as ambient globals. Deterministic tests import pure contracts directly. Artifact runtime tests use an explicit opt-in test bridge that is unavailable unless the harness sets the test flag before application startup. + +CSS remains build-time concatenated because CSS modules do not improve the standalone runtime contract. Cascade order is explicit through numeric filenames, and each file owns tokens, base rules, layout, components, or one feature family. Release chronology belongs in `CHANGELOG.md`, not stylesheet comments. + +## Consequences + +- Source composition is validated from the ESM graph instead of a manually ordered classic-script manifest. +- Builds require esbuild, already pinned for the editor adapter. +- Module cycles and undeclared cross-file dependencies are blocking validation failures. +- Runtime smoke must stop depending on arbitrary VM ambient bindings. +- The standalone artifact, offline behavior, public UI, IDs, selectors, ARIA contracts, locales, and keyboard behavior remain unchanged. +- `design_system.md` must describe the actual typography and breakpoint ranges before Item 9 closes. + +## Rejected Alternatives + +- Keeping ordered classic-script concatenation as the final architecture. +- Generating one synthetic source module by concatenating the same fragments. +- Shipping native modules, import maps, or adjacent JavaScript files at runtime. +- Introducing a broad mutable application context to simulate globals. +- Adding a framework, event bus, service split, or API-first boundary without a product requirement. +- Changing visible behavior during the ownership refactor without independent defect evidence. + +## Verification + +- Static validation parses every application source as a module, rejects undeclared source files, and rejects module cycles. +- The build produces one inline application IIFE with no external imports, source maps, `eval`, or dynamic code construction. +- Deterministic contracts import source modules directly. +- Readable and release runtime suites pass against the generated artifacts. +- The three-locale desktop/mobile browser matrix passes with zero Axe violations. +- Visual comparison covers the shell, file actions, editor actions, history, settings, SQL Map, export, and populated results before and after the refactor. diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..12e586d --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,45 @@ +# Architecture + +## Product boundary + +hSQLite Editor is one browser application distributed as one offline-capable HTML file. SQLite execution, persistence, import/export, and UI behavior run locally in the browser. There is no application backend and no remote data service. + +## Source ownership + +- `src/core/`: domain contracts, pure helpers, runtime configuration, and authoritative application state. +- `src/ports/`: browser storage, file access, clipboard/download, and SQL worker adapters. +- `src/capabilities/`: user workflows and application orchestration. +- `src/ui/`: rendering, feature composition, and event binding. +- `src/styles/`: design tokens, components, feature layouts, and responsive behavior. +- `src/editor/`: the only adapter allowed to import editor-runtime packages. +- `scripts/`: deterministic build, release, and verification tooling. +- `packaging/linux/`: declarative Linux desktop-integration inputs for the standalone artifact. +- `vendor/`: pinned binary/runtime assets with SHA-256 provenance in `vendor/manifest.json`. + +## Runtime invariants + +1. `appState` is authoritative for durable in-memory product state. +2. Browser storage is an adapter, not the source of truth while the application is running. +3. SQL execution occurs in a worker and adopts changed database bytes only after successful completion. +4. The generated artifact performs no required network request. +5. `src/app.mjs` is the sole production entry point. Every cross-file dependency is an ESM import/export, and module cycles are blocking failures. +6. User-facing copy and locale formatting are owned by the localization capability. +7. Generated `index.html` and `dist/` files are outputs, not hand-maintained source. + +## Build composition + +`scripts/app-bundle.mjs` links the source graph with the pinned esbuild version and emits one browser IIFE. `scripts/build.mjs` inlines that IIFE, the CodeMirror adapter, vendored SQL.js, boot metadata, and the numerically ordered CSS ownership files into the standalone HTML artifact. Browsers never resolve source modules or fetch runtime dependencies. + +The application keeps one authoritative `appState` in `src/core/10-state-root.js`. Narrow state modules expose domain accessors over that same object; they do not create mirrors. Feature-owned transient values such as editor handles, active workers, drag state, timers, and render caches remain outside durable application state. + +DOM registries and styles are split by owned surface. Numeric filenames define deterministic CSS cascade order only; release chronology is recorded in `CHANGELOG.md`. + +The Linux filesystem stage is a packaging satellite over the same versioned HTML artifact. It adds no second runtime, service, persistence layer, file association, or protocol handler. Its launcher resolves the packaged HTML relative to the installed prefix and delegates that one local path to `xdg-open`; [linux-packaging.md](linux-packaging.md) defines the complete boundary. + +## Architectural change policy + +Preserve the modular monolith and standalone distribution unless evidence shows they no longer serve the product. The CodeMirror 6 decision is recorded in `docs/adr/0001-codemirror-6-editor-runtime.md`; the ESM graph and standalone linker decision is recorded in `docs/adr/0002-esm-application-module-graph.md`. + +SQL.js runtime files are vendored and hash-verified. The CodeMirror 6 editor is bundled at build time from the exact lockfile behind `src/editor/codemirror6-adapter.mjs`; `runtime-components.json` records every package included in that shipped bundle. + +CodeMirror and Lezer remain development dependencies because browsers receive their compiled inline bundle, not npm packages. `runtime-components.json` and `sbom.spdx.json` are the authoritative provenance records for those shipped runtime components; generation fails if esbuild inputs and the lockfile dependency closure disagree. diff --git a/docs/linux-packaging.md b/docs/linux-packaging.md new file mode 100644 index 0000000..31aaab3 --- /dev/null +++ b/docs/linux-packaging.md @@ -0,0 +1,38 @@ +# Linux Packaging + +hSQLite Editor remains a browser application distributed as one standalone HTML file. The Linux integration is a packaging satellite: it adds a launcher, desktop entry, AppStream metadata, and icon without creating a second application runtime. + +## Contract + +- `npm run stage:linux` builds the exact versioned release HTML and creates `dist/linux/hsqlite-editor-/`. +- The staged launcher accepts no file or URL arguments. It resolves the packaged HTML relative to its installed prefix and passes that one path to `xdg-open` as a single argument. +- Launcher diagnostics follow `LC_ALL`, `LC_MESSAGES`, or `LANG` for `pt_BR` and `es_ES`, with English as the fallback. +- The desktop entry declares no MIME type, URL scheme, D-Bus activation, updater, telemetry, file association, `StartupNotify`, or `StartupWMClass`. The launcher delegates to the default browser and therefore must not claim ownership of that browser window or its startup-notification protocol. +- The staged HTML, desktop entry, AppStream metadata, and icon use mode `0644`; only `usr/bin/hsqlite-editor` uses mode `0755`. +- `SHA256SUMS` inside the stage root covers every staged installable file. Timestamps derive from the matching `CHANGELOG.md` release date, not wall-clock time. +- Packaging sources and generated metadata use MIT, the project license authorized for this repository. +- The AppStream release version and date derive from `package.json` and the matching `CHANGELOG.md` heading. `npm run bump:patch` synchronizes them locally; release PRs must pass `npm run validate:linux-metadata`, and `npm run generate:linux-metadata` is the only supported repair command after automated changelog/version updates. + +The installed layout is: + +```text +usr/bin/hsqlite-editor +usr/share/hsqlite-editor/hsqlite-editor.html +usr/share/applications/io.github.helbertm.hsqlite-editor.desktop +usr/share/doc/hsqlite-editor/LICENSE +usr/share/doc/hsqlite-editor/THIRD_PARTY_NOTICES.md +usr/share/metainfo/io.github.helbertm.hsqlite-editor.metainfo.xml +usr/share/icons/hicolor/scalable/apps/io.github.helbertm.hsqlite-editor.svg +``` + +Run `npm run validate:linux` before handing the stage tree to a distribution-specific package builder. The command validates a repeated deterministic stage, exact file set, permissions, checksum coverage, launcher argument isolation, desktop-entry invariants, XML structure, localized metadata, and path leakage. On Linux, it also consumes `desktop-file-validate` and `appstreamcli` when those system validators are installed. + +`npm run validate:linux:system` is the strict distribution-host gate. It fails when `appstreamcli`, `desktop-file-validate`, or `xdg-open` is absent and rejects pedantic AppStream findings. CI runs it on Ubuntu 24.04 through the `Linux Package / validate` check. + +The source metadata follows the freedesktop.org [Desktop Entry](https://specifications.freedesktop.org/desktop-entry/latest-single/), [Icon Theme](https://specifications.freedesktop.org/icon-theme/latest/), and [menu category](https://specifications.freedesktop.org/menu/latest/category-registry.html) specifications. AppStream claims remain intentionally narrower than the browser application's feature set so package catalogs do not imply native integrations that are absent. + +## Trust Limits + +The repository does not publish a `.deb`, `.rpm`, Flatpak, AppImage, or archive merely by creating the stage tree. Any future binary package is a new release subject and must be added to release checksums, provenance attestations, and SBOM/release-asset verification before publication. + +Actual desktop integration remains a host-native Linux gate. A release reviewer must install through the intended package manager, confirm that the launcher opens only the packaged local HTML through the system browser, and record the distribution, desktop environment, browser, package digest, and result. Container validation cannot prove desktop-session behavior. diff --git a/docs/localization.md b/docs/localization.md new file mode 100644 index 0000000..72ff659 --- /dev/null +++ b/docs/localization.md @@ -0,0 +1,28 @@ +# Localization + +## Supported locales + +The interface supports canonical BCP 47 tags `pt-BR`, `es-ES`, and `en-US`. `en-US` is the final fallback. Locale selection is stored locally and updates the document `lang` attribute. + +The workspace shell and advanced runtime flows use stable catalog keys in all three locales. This includes status and error guidance, SQL Map, table population, export, history, favorites, file actions, settings, help, accessibility names, and empty states. + +## Rules + +- Use stable catalog keys for interface copy. +- Do not place user-facing strings directly in feature modules or templates when a catalog key can represent them. +- Use the shared `Intl` formatter helpers for numbers, dates, relative time, and collation. +- Keep SQL identifiers and user data unchanged. Locale affects presentation, not stored database content or generated SQL semantics. +- Preserve placeholders such as `{count}` and `{name}` across every catalog. +- Help, accessibility names, status messages, validation errors, and empty states are part of the localization surface. +- Design for Spanish text expansion without clipping or fixed-width assumptions. + +## Adding or changing copy + +1. Add the key and `en-US` value. +2. Add reviewed `pt-BR` and `es-ES` translations. +3. Run `npm run validate:i18n`. +4. Exercise all three locales with the browser locale smoke test. + +The localization gate rejects uncataloged visible template copy, direct visible DOM assignments, status and announcement sink literals, non-catalog-backed toast arguments, and dynamic HTML copy. It also requires every stable message code emitted by the SQL worker to exist in the three catalogs. Its mutation fixtures prove that each detector fails when representative uncataloged copy is introduced. Catalog parity alone still does not prove linguistic quality, so browser flows exercise all three locales at desktop and mobile dimensions. + +Machine translation may assist drafting but does not replace contextual review. Do not translate technical tokens, filenames, SQL keywords shown as code, or keyboard key names unless the platform convention differs. diff --git a/docs/privacy.md b/docs/privacy.md new file mode 100644 index 0000000..d58f5bb --- /dev/null +++ b/docs/privacy.md @@ -0,0 +1,48 @@ +# Privacy and Local Data + +## Data flow + +hSQLite Editor runs in the browser and has no application backend, analytics service, or required telemetry endpoint. The standalone artifact does not intentionally upload database bytes, SQL text, history, favorites, settings, or file metadata. Data leaves the browser only when the user explicitly downloads, exports, copies, or shares it, or when browser/extension/operating-system behavior outside the project trust boundary does so. + +Browser storage is local to a browser profile and origin. It is not encrypted application storage and must not be treated as a secrets vault. Storage behavior for `file://` pages varies by browser; use the browser's site-data controls for the artifact origin when removing all data. + +## localStorage inventory + +The application can store these entries: + +| Key | Content | Removal | +| --- | --- | --- | +| `hSQLiteEditorStorageSchemaVersion` | Internal storage schema version. | Clear browser site data. | +| `hSQLiteEditorSqlTabsV1` | Up to five tab identifiers, titles, SQL text, and active-tab counters when session persistence is enabled. | Turning session persistence off clears this entry. Clearing browser site data also removes it. | +| `hSQLiteEditorSessionPersistenceV1` | Whether SQL tab restoration is enabled. | Change the setting or clear browser site data. | +| `hSQLiteEditorFirstRunDoneV1` | Whether first-run preferences were completed. | Clear browser site data. | +| `hSQLiteEditorQueryHistoryV1` | Up to 50 SQL statements with execution time, success/error status, and error text. | Use **Clear history** or clear browser site data. | +| `hSQLiteEditorFavoritesV1` | Up to 50 saved SQL statements with identifiers and creation times. | Use **Clear favorites** or clear browser site data. | +| `hSQLiteEditorThemeV1` | Selected light/dark theme. | Change the setting or clear browser site data. | +| `hSQLiteEditorTabNamePresetV1` | Selected tab-name preset. | Change the setting or clear browser site data. | +| `hSQLiteEditorSchemaCollapsedV1` | Schema-panel collapsed state. | Change the panel state or clear browser site data. | +| `hSQLiteEditorSchemaFiltersV1` | Schema object-type filter preferences. | Use the schema filter reset where applicable or clear browser site data. | +| `hSQLiteEditorRecentDbsV1` | Up to 10 recent-database metadata records. | Use **Clear recent databases** or clear browser site data. | +| `hSQLiteEditorLastSettingsExportAtV1` | Timestamp of the last settings export. | Clear browser site data. | +| `hSQLiteEditorLastSeenReleaseVersionV1` | Last acknowledged application version. | Clear browser site data. | +| `hSQLiteEditorLocaleV1` | Selected `en-US`, `pt-BR`, or `es-ES` locale. | Change the locale or clear browser site data. | + +SQL Map positions use dynamic keys beginning with `hSQLiteEditorSqlMapPositionsV1:`. They contain table-node coordinates associated with the current database session identifier. Virtual relationships are session-only and are not persisted. Clear browser site data to remove saved positions. + +Turning session persistence off clears only persisted SQL tabs. It does not clear history, favorites, recent-database metadata, file handles, display preferences, release state, or SQL Map positions. + +## Recent database metadata + +Each recent item can contain `id`, `name`, `path`, `size`, `lastModified`, `lastOpenedAt`, and `hasHandle`. Depending on browser file APIs, `path` is normally the selected file name or a browser-provided relative path, not an unrestricted operating-system path. SQLite database bytes are not persisted in localStorage or IndexedDB by this feature. + +## IndexedDB file handles + +Browsers that support the File System Access API can store user-selected file handles in the IndexedDB database `hSQLiteEditorFileHandlesV1`. A handle is a browser-managed reference, not a copy of the database. Reopening a recent file checks or requests read permission again before reading it. + +**Clear recent databases** removes both the localStorage recent-item list and all handles in `hSQLiteEditorFileHandlesV1`. To revoke a file permission retained by the browser itself, use the browser's file permission or site-permission controls. To remove every application record, clear browser site data for the Pages origin or standalone-file origin. Browser UI and `file://` origin grouping differ by browser. + +## Settings transfer and exports + +Settings export includes only the scopes selected by the user: favorites, query history, theme, locale, persisted SQL tabs/session preference, and tab-name preset. The JSON file leaves browser storage only through an explicit download. Result exports, saved SQL, SQLite saves, schema exports, and SQL Map PNG files are also explicit downloads. + +Before sharing an export, inspect it for SQL text, identifiers, error messages, or metadata that may be confidential. Clearing application storage does not delete files already downloaded or copied elsewhere. diff --git a/docs/releasing.md b/docs/releasing.md new file mode 100644 index 0000000..490669b --- /dev/null +++ b/docs/releasing.md @@ -0,0 +1,26 @@ +# Release Process + +1. Confirm the release PR contains the intended version and changelog. +2. Run `npm run generate:linux-metadata` and require `npm run validate:linux-metadata` to pass so AppStream version/date metadata matches the release PR. +3. Run `npm run validate:full:ci` from a clean worktree. The command validates the complete tracked and untracked repository surface before and after the release gate. +4. Run `npm run validate:dependencies`, `npm run quality:docker`, and `npm run quality:security:docker`. The first two validate repo-owned and offline-valid controls; the last command intentionally uses update mode for current npm and OSV advisory data. +5. Inspect both readable `index.html` and minified `dist/hSQLite-Editor-v.html` artifacts. +6. Run the browser locale/accessibility matrix on the generated artifact. +7. Run `npm run validate:native:chromium`, then open the final artifact directly with `file://` in current Safari and complete changed assistive-technology spot checks. +8. Confirm no runtime network request is required and no machine-local path is present. +9. Run `npm run validate:linux`; when publishing a distribution-specific Linux package, complete the host-native installation and desktop-session check defined in [linux-packaging.md](linux-packaging.md). +10. Merge the release PR only after all required GitHub checks pass. +11. Verify the GitHub release attachment and Pages deployment match the `hsqlite-editor-v` tag. +12. Verify `SHA256SUMS` and `sbom.spdx.json` are attached to the release, and verify both the provenance and SPDX SBOM attestations for the exact HTML artifact. + +The exact order and ownership of static, contract, artifact/runtime, browser, security, and host-native checks is defined in [validation.md](validation.md). Do not replace a failed focused layer with a passing broader layer. + +`index.html` and `sbom.spdx.json` are tracked, reproducible release evidence. Versioned `dist/` artifacts, `SHA256SUMS`, and the temporary Pages `_site/` tree are generated outputs and must not be committed as release history. + +Generate and verify the portable checksum file with `npm run generate:release-checksums` and `npm run validate:release-assets`. After publication, verify provenance with `gh attestation verify dist/hSQLite-Editor-v.html --repo /`. Verify the associated SPDX predicate by adding `--predicate-type https://spdx.dev/Document/v2.3`. + +The SBOM generator derives `creationInfo.created` from the current version's release date in `CHANGELOG.md`, normalized to `00:00:00Z`. This is an intentional canonical source-release timestamp, not the wall-clock time of a generator process. It is reproducible and must exist before the release gate passes. The SBOM inventories both vendored runtime assets and every locked development/release package. + +Repository automation cannot enforce GitHub rulesets, required checks, private vulnerability reporting, environment protection, or trusted publishing. Maintainers must configure and periodically audit those settings in GitHub. + +The default-branch ruleset should require pull requests and the repository-owned `Quality Gate / validate`, `Linux Package / validate`, `Browser Quality / locale-accessibility`, `CodeQL / Analyze JavaScript`, `Commit Convention Check / conventional-commits`, and `Dependency Review / dependency-review` checks. Require code-owner review when at least one independent eligible reviewer exists; do not create an unsatisfiable review policy for a single-maintainer repository. Restrict the `github-pages` environment to `master`, disable administrator bypass when governance permits it, enable Private Vulnerability Reporting, and keep the default `GITHUB_TOKEN` read-only unless a job declares narrower write permissions. diff --git a/docs/remediation-execution-plan.md b/docs/remediation-execution-plan.md new file mode 100644 index 0000000..1183e98 --- /dev/null +++ b/docs/remediation-execution-plan.md @@ -0,0 +1,216 @@ +# Open-Source Remediation Execution Plan + +## Objective + +Bring hSQLite Editor to a defensible state-of-the-art open-source publication baseline while preserving one local-first browser application and one offline standalone HTML artifact. + +This plan is sequential. An item cannot start until the previous item has three independent checks recorded in the evidence report identified by the master formal review. + +## Source Reports + +- BurleMarx formal review: `8159e6e7-c6bb-4477-8968-06455c0f5f66` +- Da Vinci formal review: `74E3C753-B97F-466C-B9A5-2E17C8969128` +- Angela Jobson formal review: `8dcad054-e431-4029-9e9d-407fa41a374b` +- Linus Swartz formal review: `e4652b54-2459-4417-adef-6282046b90ea` +- Consolidated master review: `5EC55094-5711-47C5-BADE-A5C8C3A40748` + +## Transition Protocol + +Before item N starts, item N-1 must pass: + +1. **Structural check** — source ownership, schema, diff, inventory, or static policy. +2. **Executable contract check** — focused repo-owned deterministic validation. +3. **Independent integration check** — artifact runtime, browser, host-native, security runtime, or post-run cleanliness. + +The evidence record must include timestamp, exact command or inspection, exit status, target, interpretation, and trust limits. Repeating one test three times is not a triple check. + +## Gate 0 — Formal Review Package + +### Deliverables + +- Four fresh UUID-based individual reports. +- One UUID-based consolidated report. +- This execution plan. +- One append-only remediation evidence report. + +### Exit Criteria + +- Every specialist identity, version, mantra, language, artifact folder, and review-only boundary was confirmed before review. +- Every report contains severity, file/line evidence, required actions, and triple-check acceptance criteria. +- The master report references every report UUID and preserves specialist-owned decisions. + +## Item 1 — Repository Baseline and Artifact Policy + +### Scope + +- Define the intended public tracked-file surface. +- Keep `agent-state/`, machine-local `.codex` configuration, caches, dependencies, and generated release history out of public tracking. +- Keep readable `index.html` as tracked generated evidence. +- Keep versioned `dist/` HTML and release checksums as generated release outputs, not source-controlled history. +- Make clean-worktree validation inspect the complete intended delivery surface. +- Align `.gitignore`, build scripts, CI workflows, and release documentation. + +### Exit Criteria + +- No intended source, workflow, dependency manifest, vendor asset, governance file, or public document is omitted from the tracked baseline. +- `validate:full:ci` has one unambiguous clean-worktree contract. +- A full clean preflight does not leave new tracked or untracked product output. + +## Item 2 — Settings Import Integrity + +### Scope + +- Enforce selected import scopes. +- Validate payload version, allowed keys, object/array types, string sizes, collection sizes, locale/theme values, and tab/session shapes. +- Reject unknown or oversized payloads. +- Apply imports atomically after complete validation. +- Add focused contract tests for scope isolation and failure preservation. + +### Exit Criteria + +- Import changes only selected scopes. +- Invalid payloads cannot partially mutate storage or runtime state. +- Focused tests cover valid, malformed, oversized, unknown-key, and atomic-failure cases. + +## Item 3 — Localization Source of Truth + +### Scope + +- Make stable keys the only source for user-facing application copy. +- Replace Portuguese source-text translation and `STATIC_SOURCE_KEYS`. +- Add explicit template localization attributes or keyed rendering. +- Return stable worker error/status codes plus interpolation variables. +- Localize boot, status, toast, history, favorites, export, SQL Map, table population, settings, and error-assistance flows. +- Keep user data, SQL identifiers, and SQL text unchanged. + +### Exit Criteria + +- No release-visible copy depends on Portuguese source fallback. +- All catalog keys and interpolation variables match across `en-US`, `pt-BR`, and `es-ES`. +- Worker-originated errors and advanced flows render in the selected locale. + +## Item 4 — SQL Map Accessibility and Help + +### Scope + +- Give every table and field checkbox a programmatic name tied to visible content. +- Verify focus order, keyboard operation, relation creation, blocked states, and announcements. +- Provide locale-appropriate or language-neutral FK-direction help. + +### Exit Criteria + +- Accessible names are asserted against a sample database. +- SQL Map has zero serious/critical axe violations when open and populated. +- Keyboard and assistive-technology spot checks announce unambiguous table and field names. + +## Item 5 — Localization and Browser Evidence Gates + +### Scope + +- Make the i18n validator reject direct user-facing strings outside approved catalog files. +- Expand browser tests to close-tab, export, history/favorites, SQL Map, table population, worker errors, and populated results. +- Cover all three locales at desktop and mobile dimensions. +- Cover keyboard paths, zoom/reflow, overflow, accessible names, and locale-specific help destinations. + +### Exit Criteria + +- Introducing a direct visible string causes `validate:i18n` to fail. +- CI exercises advanced flows rather than shell text only. +- Chromium and host-native Safari evidence references the exact release artifact. + +## Item 6 — Security, SBOM, SCA, and Privacy + +### Scope + +- Use truthful SBOM creation metadata with a documented reproducibility rule. +- Add a blocking repo-owned dependency vulnerability command. +- Integrate offline-valid checks with `codex-quality` and use an update-capable advisory fetch only where required. +- Keep scanner scope limited to owned files. +- Document localStorage, IndexedDB, recent metadata, file handles, and clearing/revocation steps. + +### Exit Criteria + +- SBOM timestamp policy is truthful, documented, and validated. +- Dependency vulnerability status is a blocking release signal. +- Public privacy/security docs enumerate exact persistence categories and removal controls. + +## Item 7 — Validation Stratification + +### Scope + +- Add a narrow deterministic contract/unit layer for pure logic and state transitions. +- Split the monolithic runtime smoke harness by ownership or reduce it to cross-surface scenarios. +- Keep static, unit/contract, artifact/runtime, browser, security, and host-only checks distinct. +- Give each layer stable repo-owned commands. + +### Exit Criteria + +- Triple checks use independent layers rather than repeated broad smoke tests. +- Failures identify the responsible layer. +- Full validation remains deterministic and documented. + +## Item 8 — Maintained Editor Runtime + +### Scope + +- Record an ADR for editor-runtime migration under the offline single-file constraint. +- Replace archived CodeMirror 5 with a maintained editor runtime. +- Preserve SQL syntax support, shortcuts, find/replace, selection, accessibility naming, themes, and artifact embedding. +- Remove obsolete vendored files and compatibility branches. + +### Exit Criteria + +- No archived CodeMirror 5 runtime ships in package metadata, vendor manifest, or generated artifact. +- Editor contract tests and browser keyboard tests pass. +- One-file offline behavior remains unchanged. + +## Item 9 — Legacy Seam Reduction + +### Scope + +- Replace ordered global composition with a build-time module graph while preserving one artifact. +- Split the root DOM registry by surface. +- Split core state contracts by domain without creating competing sources of truth. +- Split CSS by tokens/components/features and remove chronological beta-fix narration. +- Keep runtime smoke and source validation aligned with the new module boundaries. + +### Exit Criteria + +- Source composition no longer relies on broad implicit globals. +- Ownership is narrower and documented. +- Build, artifact, runtime, browser, and security gates remain green. + +## Item 10 — External Release Controls + +### Scope + +- Audit GitHub branch protection/rulesets, required checks, code-owner review, Private Vulnerability Reporting, Pages environment protection, Actions permissions, and release attestation behavior. +- Run native Chromium and Safari `file://` release smoke. +- Record checksums, SPDX SBOM, and provenance attestation for the exact artifact. + +### Exit Criteria + +- GitHub-side settings are recorded as verified or explicitly blocked with owner and evidence. +- Final standalone HTML opens without network requirements in Chromium and Safari. +- Release assets and attestations match the tagged version. + +## Final Double-Check + +### Pass 1 — Code and Product Quality + +- Inspect all touched code for duplication, dead compatibility code, naming drift, accessibility regressions, localization drift, oversized growth, and documentation mismatch. +- Implement every bounded improvement that is justified by evidence. +- Reopen and triple-check any affected item. + +### Pass 2 — Release and Trust + +- Run the clean-worktree full gate. +- Run `codex-quality`, blocking SCA, artifact/runtime validation, the three-locale browser matrix, and host-native file checks. +- Confirm the repository remains clean and the evidence report is complete. + +## Stop Conditions + +- Do not claim completion while a previous item lacks three independent checks. +- Do not classify GitHub configuration absence as a source-code defect. +- Do not classify browser harness instability as a product defect without independent reproduction. +- Do not preserve compatibility code merely because it is old; preserve it only when a current contract requires it. diff --git a/docs/validation.md b/docs/validation.md new file mode 100644 index 0000000..cb9eb4c --- /dev/null +++ b/docs/validation.md @@ -0,0 +1,43 @@ +# Validation Layers + +hSQLite Editor separates checks by failure ownership. A passing broader layer never overrides a failed focused layer. + +## Static policy + +Run `npm run validate:static` for source composition, localization ownership, accessibility contracts, privacy documentation, SPDX reproducibility, and workflow syntax. These checks inspect owned files without starting the application. + +## Deterministic unit and contract tests + +Run `npm run test:contract`. It executes `npm run test:unit` for pure SQL parsing, SQLite type classification, file validation, and authoritative state transitions, then runs the focused settings-import transaction contract. This layer does not build or boot an HTML artifact. + +## Artifact and runtime + +Run `npm run validate:artifact:structure` to inspect readable artifact composition and embedded dependency integrity. Run `npm run validate:runtime` for the narrow cross-surface contract: boot, database open, one mixed SQL path, and state-preserving database replacement. + +Feature-owned VM regressions have separate commands and fresh harness contexts: `npm run validate:runtime:database`, `npm run validate:runtime:library`, `npm run validate:runtime:execution-grid`, and `npm run validate:runtime:sql-map`. `npm run validate:runtime:features` runs those four commands; `npm run validate:runtime:all` runs the cross-surface and feature-owned suites in one command while retaining isolated contexts and suite-attributed output. + +After `npm run build:release`, run `npm run validate:release:structure` for minified artifact structure and size, then `npm run validate:release:runtime` for all isolated runtime suites on the exact versioned release file. `npm run validate:artifact` and `npm run validate:release` remain convenience aggregates; evidence should name the focused command and suite that failed or passed. + +Run `npm run validate:linux` after the release build to reproduce the Linux filesystem stage twice and verify its exact file set, permissions, checksums, desktop metadata, AppStream metadata, and isolated launcher argument. Actual desktop-session behavior remains a host-native Linux check. + +On Ubuntu or another supported Linux build host with `appstreamcli`, `desktop-file-validate`, and `xdg-open`, run `npm run validate:linux:system`. It requires those tools, reruns the deterministic stage, rejects any pedantic AppStream finding, and validates the desktop entry with the distribution tooling. The `Linux Package / validate` workflow owns this gate on Ubuntu 24.04. + +## Browser + +Run `npm run validate:browser:quality` against the exact served release URL. The matrix owns real Chromium rendering, interaction, responsive reflow, locale behavior, accessible names, downloads, and axe results. `npm run validate:browser:backlog` is a focused real-worker regression command and is not a replacement for the quality matrix. + +## Security and reproducibility + +Run `npm run validate:dependencies` for blocking current npm advisory status. Run `npm run quality:docker` for the offline/read-only `codex-quality` surface and `npm run quality:security:docker` for update-capable npm and OSV analysis. On a new machine, run `npm run quality:docker:update` once to populate the container cache from the lockfile, then require `npm run quality:docker` to pass with networking disabled. Network or scanner failure blocks an update-capable command. + +## Host-native release checks + +Native Chromium and Safari checks open the exact versioned artifact through `file://`. They own host browser launch, direct-file boot, zero required network resources, locale selection, overflow, keyboard behavior, and changed assistive-technology spot checks. They are intentionally outside `npm run validate:full` and Docker; release evidence must record the browser version, artifact SHA-256, timestamp, and observed result. + +`npm run validate:native:chromium` automates the direct-file boot, remote-request, locale-selector, and horizontal-overflow subset against the installed Chrome channel. Set `HSQLITE_NATIVE_CHROMIUM_CHANNEL` only to select another locally installed Playwright Chromium channel. Native Safari and changed assistive-technology checks remain separate because they require host facilities that the Node dependency graph does not provide. + +## Orchestration + +`npm run validate:full` runs static policy, deterministic contracts, readable structure, cross-surface runtime, feature-owned runtime, release structure/runtime, deterministic Linux staging, and approval gates in that order. `npm run validate:full:ci` adds clean-repository checks before and after the same sequence. Browser, security-update, and host-native checks remain separate because their environments and failure modes are independent. + +Repository-state validation also rejects legacy CodeMirror 5 paths from the Git index. This protects release candidates from staged content that differs from the clean worktree and artifact scans. diff --git a/index.html b/index.html index d34f07f..49ea426 100644 --- a/index.html +++ b/index.html @@ -1,25 +1,15 @@ - + - hSQLite Editor v0.1beta - - - - - - + + hSQLite Editor v0.3.143 - +th.column-drop-after::after { +right: 0; +} - -
-
-
-

hSQLite Editor v0.1.1

-
Para trabalhar e estudar
-
+.result-toolbar.toolbar-hidden { +display: none !important; +} -
-
+.toolbar-group { +display: inline-flex; + align-items: center; + gap: 8px; + flex-wrap: wrap; + min-width: 0; +} -
-
-
-
- - Arquivo de dados - - -
- - - - -
-
- - +.toolbar-spacer { +flex: 1 1 auto; + min-width: 12px; +} - - -
-
+@media (max-width: 1100px) { +.toolbar-spacer { +display: none; +} +} -
- - +@media (max-width: 720px) { +.app-header, + .header-actions, + .top-command-bar, + .toolbar-group { +align-items: flex-start; + justify-content: flex-start; +} -
-
-
- -
-
-
-

Instruções SQL

-
- - - - +.result-toolbar { +display: grid; + grid-template-columns: minmax(180px, 1fr) auto auto; + align-items: center; +} -
- Mais -
- - - - - - - - - - -
-
-
-
-
- - -
-
- -
Solte o arquivo aqui
- Arquivos .sql, .txt ou texto puro -
-
-
-
- - 0/0 - - - - -
-
- - - -
-
-
-
-
-
-
Carregue um arquivo .db para começar.
-
-
- - Executando consulta... - · - Tempo decorrido: 0s - -
-
-
Erro SQL
-
-
+.result-toolbar .pagination { +grid-column: 1 / -1; + margin-left: 0; + justify-content: flex-start; +} +} -
+@media (max-width: 560px) { +.result-toolbar { +grid-template-columns: minmax(0, 1fr); +} -
-
-

Resultados

-
- - -
-
-
+.result-toolbar .ui-button, + .result-toolbar select, + .result-toolbar .filter-wrap { +width: 100%; + max-width: none; +} +} -
-
-
-

Nenhum resultado para exibir

-

Abra um banco SQLite, escreva uma consulta e execute com F5.

-
-
-
- +.execution-group, + .compact-help, + .toolbar-spacer { +display: none !important; +} -
-
-
-
-
-
-
+.result-header { +display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + margin: 0 0 8px; + flex-wrap: wrap; +} -
+.result-header h2 { +margin: 0; + font-size: 14px; + letter-spacing: 0; +} +.result-actions { +display: inline-flex; + align-items: center; + gap: 6px; + flex-wrap: wrap; +} +.result-actions .ui-button { +min-width: 104px; + min-height: 30px; + padding: 0 10px; + font-size: 12px; + justify-content: center; +} +.modal-options label.export-option-disabled { +opacity: 0.48; + cursor: not-allowed; +} +.modal-options label.export-option-disabled input { +cursor: not-allowed; +} +.export-empty-message { +display: none; + padding: 12px; + border: 1px solid var(--border); + border-radius: var(--radius); + background: var(--input-bg); + color: var(--mutedText); + font-size: 14px; + line-height: 1.4; + text-align: center; +} +.modal-options.export-empty-state label { +display: none; +} - +.export-primary-btn, + .export-cancel-btn { +flex: 1 1 auto; +} +} - +.cell-marker { +display: inline-flex; + align-items: center; + min-height: 18px; + padding: 1px 7px; + border-radius: 999px; + border: 1px solid var(--border); + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; + font-size: 11px; + font-weight: 800; + letter-spacing: 0.02em; + color: var(--mutedText); + background: color-mix(in srgb, var(--muted) 62%, transparent); +} +.cell-null { +color: color-mix(in srgb, var(--warning) 72%, var(--foreground)); + border-color: color-mix(in srgb, var(--warning) 34%, var(--border)); + background: color-mix(in srgb, var(--warning) 10%, transparent); +} - - +.cell-empty { +color: color-mix(in srgb, var(--info) 68%, var(--foreground)); + border-color: color-mix(in srgb, var(--info) 30%, var(--border)); + background: color-mix(in srgb, var(--info) 9%, transparent); + text-transform: lowercase; +} - +.cell-empty { +font-style: normal; + text-transform: lowercase; +} - +th.column-draggable { +white-space: nowrap; +} - +.column-drag-handle { +display: inline-flex; + align-items: center; + justify-content: center; + width: 15px; + height: 15px; + margin-right: 7px; + color: var(--mutedText); + opacity: 0.58; + vertical-align: -2px; + cursor: grab; +} - +.column-drag-handle svg { +width: 14px; + height: 14px; + display: block; + fill: none; + stroke: currentColor; + stroke-width: 1.8; + stroke-linecap: round; + stroke-linejoin: round; +} - +th.column-draggable:hover .column-drag-handle { +opacity: 0.92; + color: var(--foreground); +} - +th.column-draggable:active .column-drag-handle { +cursor: grabbing; +} - +.column-title { +vertical-align: middle; +} - +.ui-button, + .file-label.ui-button, + .result-actions .ui-button { +display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + min-height: var(--control-height); + padding: 0 12px; + line-height: 1; + white-space: nowrap; +} +.sql-tab.has-result .sql-tab-status-dot { +opacity: 0.9; background: var(--foreground); +} - +.table-wrap tbody tr:focus-visible, +.table-wrap th[tabindex]:focus-visible { +outline: 3px solid var(--ring); + outline-offset: -3px; +} - -