Compare commits
8 Commits
72e10622ba
...
v0.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
688b87e98d | ||
|
|
52444350c1 | ||
|
|
747c42499d | ||
|
|
5a69e0bba8 | ||
|
|
d2e11b8bdd | ||
|
|
f55bd84668 | ||
|
|
61ed2717d0 | ||
|
|
548eb70d55 |
76
rules/patterns/backup-management/contract.md
Normal file
76
rules/patterns/backup-management/contract.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Contract: Backup Management
|
||||
|
||||
Version: 1.2
|
||||
|
||||
## Purpose
|
||||
|
||||
Общие правила для создания, хранения, именования, ротации и восстановления бэкапов вне зависимости от того, что именно сохраняется: SQLite, централизованная БД, конфиг, файлы пользователя или смешанный bundle.
|
||||
|
||||
## Backup Capability Must Be Shipped
|
||||
|
||||
Backup/restore must be built into the application runtime or into binaries/scripts shipped as part of the application itself. Do not assume the operator already has suitable software installed on their machine.
|
||||
|
||||
Rules:
|
||||
- AI must not rely on random machine-local applications (DB GUI clients, IDE plugins, desktop backup tools, ad-hoc admin utilities) being present on the user's machine.
|
||||
- Backup helpers must not depend on locally installed database clients such as `mysql`, `mysqldump`, `psql`, `pg_dump`, `sqlite3`, or similar tools being present on the user's machine.
|
||||
- If the application persists non-ephemeral state and does not already have backup functionality, implement it.
|
||||
- Preferred delivery is one of: built-in UI action, CLI subcommand, background scheduler, or another application-owned mechanism implemented in the project.
|
||||
- The backup path must work through application mechanics: application code, bundled libraries, and application-owned configuration.
|
||||
- Rollout instructions must reference only shipped or implemented backup/restore paths.
|
||||
|
||||
## Backup Storage
|
||||
|
||||
Backups are operational artifacts, not source artifacts.
|
||||
|
||||
Rules:
|
||||
- Never write backups into the git repository tree.
|
||||
- Backup files must never be staged or committed to git.
|
||||
- Every application must have an explicit backup root outside the repository.
|
||||
- Before creating, rotating, or restoring backups, the application must verify that the backup root resolves outside the git worktree.
|
||||
- Before creating, rotating, or restoring backups, the application must verify again that the target backup files are not tracked or staged in git.
|
||||
- Default local-app location: store backups next to the user config, for example `~/.config/<appname>/backups/`.
|
||||
- Default server/centralized location: store backups in an application-owned path outside the repository, for example `/appdata/<appname>/backups/` or `/var/backups/<appname>/`.
|
||||
- Keep retention tiers in separate directories: `daily/`, `weekly/`, `monthly/`, `yearly/`.
|
||||
|
||||
## Backup Naming and Format
|
||||
|
||||
Rules:
|
||||
- Each snapshot must be a single archive or dump artifact when feasible.
|
||||
- Backup filenames must include a timestamp and a version marker relevant to restore safety, for example schema version, migration number, app version, or backup format version.
|
||||
- If multiple artifacts are backed up independently, include the artifact identity in the filename.
|
||||
- Backups should be archived/compressed by default (`.zip`, `.tar.gz`, `.sql.gz`, `.dump.zst`, or equivalent) unless restore tooling requires a raw dump.
|
||||
- Include all sidecar files required for a correct restore.
|
||||
- Include the application config in the backup when it is required for a meaningful restore.
|
||||
|
||||
## Retention and Rotation
|
||||
|
||||
Use bounded retention. Do not keep an unbounded pile of snapshots.
|
||||
|
||||
Default policy:
|
||||
- Daily: keep 7
|
||||
- Weekly: keep 4
|
||||
- Monthly: keep 12
|
||||
- Yearly: keep 10
|
||||
|
||||
Rules:
|
||||
- Prevent duplicate backups within the same retention period.
|
||||
- Rotation/pruning must be automatic when the application manages recurring backups.
|
||||
- Pre-migration or pre-repair safety backups may be kept outside normal rotation until the change is verified.
|
||||
|
||||
## Automated Backup Behavior
|
||||
|
||||
For applications that manage recurring local or operator-triggered backups:
|
||||
|
||||
Rules:
|
||||
- On application startup, create a backup immediately if none exists yet for the current period.
|
||||
- Support scheduled daily backups at a configured local time.
|
||||
- Before migrations or other risky state-changing maintenance steps, trigger a fresh backup from the application-owned backup mechanism.
|
||||
- Before migrations or other risky state-changing maintenance steps, double-check that backup output is outside the git tree so it cannot be pushed to a remote by accident.
|
||||
- If backup location, schedule, or retention is configurable, provide safe defaults and an explicit disable switch.
|
||||
|
||||
## Restore Readiness
|
||||
|
||||
Rules:
|
||||
- The operator must know how to restore from the backup before applying risky changes.
|
||||
- Restore steps must be documented next to the backup workflow.
|
||||
- A backup that has never been validated for restore is only partially trusted.
|
||||
66
rules/patterns/build-version-display/contract.md
Normal file
66
rules/patterns/build-version-display/contract.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# Contract: Build Version Display
|
||||
|
||||
Version: 1.0
|
||||
|
||||
## Purpose
|
||||
|
||||
Every web application must display the current build version in the page footer so that users and support staff can identify exactly which version is running.
|
||||
|
||||
---
|
||||
|
||||
## Rule
|
||||
|
||||
The build version **must** be visible in the footer on every page of the web application.
|
||||
|
||||
---
|
||||
|
||||
## Requirements
|
||||
|
||||
- The version is shown in the footer on **all** pages, including error pages (404, 500, etc.).
|
||||
- The version string is injected at **build time** — it is never hardcoded in source and never fetched at runtime.
|
||||
- The version value comes from a single authoritative source (e.g. `package.json`, `version.go`, a CI environment variable). It is not duplicated manually.
|
||||
- Format: any human-readable string that uniquely identifies the build — a semver tag, a git commit SHA, or a combination (e.g. `1.4.2`, `1.4.2-abc1234`, `abc1234`).
|
||||
- The version text must be legible but visually subordinate — use a muted color and small font size so it does not compete with page content.
|
||||
|
||||
---
|
||||
|
||||
## Recommended implementation
|
||||
|
||||
**Frontend (JS/TS build tools)**
|
||||
|
||||
Expose the version through an environment variable at build time and reference it in the footer component:
|
||||
|
||||
```ts
|
||||
// vite.config.ts / webpack.config.js
|
||||
define: {
|
||||
__APP_VERSION__: JSON.stringify(process.env.APP_VERSION ?? "dev"),
|
||||
}
|
||||
|
||||
// Footer component
|
||||
<footer>v{__APP_VERSION__}</footer>
|
||||
```
|
||||
|
||||
**Go (server-rendered HTML)**
|
||||
|
||||
Inject via `-ldflags` at build time and pass to the template:
|
||||
|
||||
```go
|
||||
// main.go
|
||||
var Version = "dev"
|
||||
|
||||
// Build: go build -ldflags "-X main.Version=1.4.2"
|
||||
```
|
||||
|
||||
```html
|
||||
<!-- base template -->
|
||||
<footer>v{{ .Version }}</footer>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What is NOT allowed
|
||||
|
||||
- Omitting the version from any page, including error pages.
|
||||
- Fetching the version from an API endpoint at runtime (network dependency for a static value).
|
||||
- Hardcoding a version string in source code.
|
||||
- Storing the version in more than one place.
|
||||
@@ -1,6 +1,6 @@
|
||||
# Contract: Go Code Style and Project Conventions
|
||||
|
||||
Version: 1.0
|
||||
Version: 1.1
|
||||
|
||||
## Logging
|
||||
|
||||
@@ -64,6 +64,7 @@ Never reverse steps 2 and 5. Never start serving before migrations complete.
|
||||
- Never hardcode ports, DSNs, or file paths in application code.
|
||||
- Provide a `config.example.yaml` committed to the repo.
|
||||
- The actual `config.yaml` is gitignored.
|
||||
- Secret handling and pre-commit/pre-push leak checks must follow the `secret-management` contract.
|
||||
|
||||
## Template / UI Rendering
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Contract: Database Patterns (Go / MySQL / MariaDB)
|
||||
|
||||
Version: 1.0
|
||||
Version: 1.9
|
||||
|
||||
## MySQL Transaction Cursor Safety (CRITICAL)
|
||||
|
||||
@@ -104,9 +104,123 @@ items, _ := repo.GetItemsByPricelistIDs(ids) // 1 query with WHERE id IN (...)
|
||||
// then group in Go
|
||||
```
|
||||
|
||||
## Automatic Backup During Migration
|
||||
|
||||
The migration engine is responsible for all backup steps. The operator must never be required to take a backup manually.
|
||||
|
||||
Backup naming, storage, archive format, retention, and restore-readiness must follow the `backup-management` contract.
|
||||
|
||||
### Full DB Backup on New Migrations
|
||||
|
||||
When the migration engine detects that new (unapplied) migrations exist, it must take a full database backup before applying any of them.
|
||||
|
||||
Rules:
|
||||
- The full backup must complete and be verified before the first migration step runs.
|
||||
- The backup must be triggered by the application's own backup mechanism; do not assume `mysql`, `mysqldump`, `pg_dump`, or any other external DB client tool is present on the operator's machine.
|
||||
- Before creating the backup, verify that the backup output path resolves outside the git worktree and is not tracked or staged in git.
|
||||
|
||||
### Per-Table Backup Before Each Table Migration
|
||||
|
||||
Before applying a migration step that affects a specific table, take a targeted backup of that table.
|
||||
|
||||
Rules:
|
||||
- A per-table backup must be created immediately before the migration step that modifies that table.
|
||||
- If a single migration step touches multiple tables, back up each affected table before the step runs.
|
||||
- Per-table backups are in addition to the full DB backup; they are not a substitute for it.
|
||||
|
||||
### Session Rollback on Failure
|
||||
|
||||
If any migration step fails during a session, the engine must roll back all migrations applied in that session.
|
||||
|
||||
Rules:
|
||||
- "Session" means all migration steps started in a single run of the migration engine.
|
||||
- On failure, roll back every step applied in the current session in reverse order before surfacing the error.
|
||||
- If rollback of a step is not possible (e.g., the operation is not reversible in MySQL without the per-table backup), restore from the per-table backup taken before that step.
|
||||
- After rollback or restore, the database must be in the same state as before the session started.
|
||||
- The engine must emit structured diagnostics that identify which step failed, which steps were rolled back, and the final database state.
|
||||
|
||||
## Migration Policy
|
||||
|
||||
- For local-first desktop applications, startup and migration recovery must follow the `local-first-recovery` contract.
|
||||
- Migrations are numbered sequentially and never modified after merge.
|
||||
- Each migration must be reversible where possible (document rollback in a comment).
|
||||
- Never rename a column in one migration step — add new, backfill, drop old across separate deploys.
|
||||
- Auto-apply migrations on startup is acceptable for internal tools; document if used.
|
||||
|
||||
## SQL Migration File Format
|
||||
|
||||
Every `.sql` migration file must begin with a structured header block:
|
||||
|
||||
```sql
|
||||
-- Tables affected: supplier, lot_log
|
||||
-- recovery.not-started: No action required.
|
||||
-- recovery.partial: DELETE FROM parts_log WHERE created_by = 'migration';
|
||||
-- recovery.completed: Same as partial.
|
||||
-- verify: No orphaned supplier_code | SELECT supplier_code FROM parts_log pl LEFT JOIN supplier s ON s.supplier_code = pl.supplier_code WHERE s.supplier_code IS NULL LIMIT 1
|
||||
-- verify: No empty supplier_code | SELECT supplier_name FROM supplier WHERE supplier_code = '' LIMIT 1
|
||||
```
|
||||
|
||||
**`-- Tables affected:`** — comma-separated list of tables the migration touches. Used by the backup engine to take a targeted pre-migration backup. Omit only if no table can be identified; the engine falls back to full DB backup.
|
||||
|
||||
**`-- recovery.*:`** — human-readable rollback SQL for each migration state (`not-started`, `partial`, `completed`). Executed manually by an operator if automatic restore fails. Must be correct, copy-pasteable SQL.
|
||||
|
||||
**`-- verify:`** — post-migration assertion query. Format: `-- verify: <description> | <SQL>`. The engine runs the query after all statements in the file succeed. If the query returns **any row**, the migration is considered failed and is rolled back. Write the query so it returns a row only when something is **wrong**:
|
||||
|
||||
```sql
|
||||
-- verify: Orphaned FK refs | SELECT id FROM child c LEFT JOIN parent p ON p.id = c.parent_id WHERE p.id IS NULL LIMIT 1
|
||||
-- ^ returns a row = bad ^ returns nothing = good
|
||||
```
|
||||
|
||||
- Verify queries must filter out NULL/empty values that would cause false positives: add `AND col IS NOT NULL AND col != ''`.
|
||||
- A migration is only recorded as applied after all verify checks pass.
|
||||
- Verify checks are not a substitute for testing; they are a last-resort safety net on production.
|
||||
|
||||
## Pre-Production Migration Testing in Docker
|
||||
|
||||
Before applying a set of new migrations to production, always validate them against a copy of the production database in a local MariaDB Docker container that matches the production version and collation.
|
||||
|
||||
```bash
|
||||
# Start container matching production (MariaDB 11.8, utf8mb4_uca1400_ai_ci)
|
||||
docker run -d --name pf_test \
|
||||
-e MYSQL_ROOT_PASSWORD=test -e MYSQL_DATABASE=RFQ_LOG \
|
||||
mariadb:11.8 --character-set-server=utf8mb4 --collation-server=utf8mb4_uca1400_ai_ci
|
||||
|
||||
# Load production dump
|
||||
docker exec -i pf_test mariadb -uroot -ptest RFQ_LOG < prod_dump.sql
|
||||
|
||||
# Run migrations via pfs (uses real migration engine + verify checks, no backup)
|
||||
./pfs -migrate-dsn "root:test@tcp(127.0.0.1:3306)/RFQ_LOG?parseTime=true&charset=utf8mb4&multiStatements=true" \
|
||||
-no-backup -verbose
|
||||
```
|
||||
|
||||
The `-migrate-dsn` flag connects to the given DSN, runs all pending migrations, runs verify checks, and exits. No config file, no server, no browser.
|
||||
|
||||
**Rules:**
|
||||
- Always test on a dump of the **current production database**, not a fixture — schema drift and real data distributions expose bugs that fixtures miss.
|
||||
- The Docker container must use the same MariaDB version and `--collation-server` as production.
|
||||
- Each migration file is executed as a **single session** so `SET FOREIGN_KEY_CHECKS = 0` applies to all its statements. Never test by running statements from a migration file individually across separate sessions — the session variable will reset between them.
|
||||
- If any migration fails in Docker, fix the SQL before touching production. Do not rely on "it will be different in production."
|
||||
|
||||
## SQL Migration Authoring — Common Pitfalls
|
||||
|
||||
**Semicolons inside string literals break naive splitters.**
|
||||
The migration engine uses a quote-aware statement splitter. Do not rely on external tools that split on bare `;`. When writing supplier/product names with punctuation, use commas — not semicolons — as separators in string literals. A semicolon inside `'COMPANY; LTD'` will break any naive `split(";")` approach.
|
||||
|
||||
**`SET FOREIGN_KEY_CHECKS = 0` only applies to the current session.**
|
||||
This is a session variable. If statements run in separate connections (e.g. via individual subprocess calls), FK checks are re-enabled for each new connection. Always run an entire migration file as one session. The pfs migration engine runs all statements in a file on the same GORM db handle, which reuses the same connection.
|
||||
|
||||
**Verify queries must exclude NULL values.**
|
||||
A query like `SELECT c.col FROM child c LEFT JOIN parent p ON p.id = c.id WHERE p.id IS NULL` will return rows with `c.col = NULL` if the child table has rows with a NULL FK value. Add `AND c.col IS NOT NULL AND c.col != ''` to avoid false failures.
|
||||
|
||||
**Catch-all INSERT for referential integrity before adding FK constraints.**
|
||||
When adding a FK constraint to a table that previously had no FK (legacy data may have orphaned references), add a catch-all step before the constraint:
|
||||
|
||||
```sql
|
||||
-- Ensure every value referenced in child table exists in parent before adding FK.
|
||||
INSERT IGNORE INTO parent (name)
|
||||
SELECT DISTINCT c.fk_col FROM child c
|
||||
LEFT JOIN parent p ON p.name = c.fk_col
|
||||
WHERE p.name IS NULL AND c.fk_col IS NOT NULL AND c.fk_col != '';
|
||||
```
|
||||
|
||||
This is not a hack — it repairs data that was valid before the constraint existed. Never delete orphaned child rows unless data loss is acceptable.
|
||||
|
||||
95
rules/patterns/local-first-recovery/contract.md
Normal file
95
rules/patterns/local-first-recovery/contract.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# Contract: Local-First Recovery
|
||||
|
||||
Version: 1.2
|
||||
|
||||
## Purpose
|
||||
|
||||
Shared recovery and migration rules for local-first desktop applications that keep local state and may rebuild part of that state from sync, reload, import, or other deterministic upstream sources.
|
||||
|
||||
## Core Rule
|
||||
|
||||
A migration or startup strategy is not considered sufficient merely because it succeeded once on the current developer database.
|
||||
|
||||
Priority order:
|
||||
- Priority 1: protect user data. Do not do anything that can damage, discard, or silently rewrite non-recoverable user data.
|
||||
- Priority 2: preserve availability. Do not do anything that unnecessarily prevents the application from starting or operating in a reduced mode.
|
||||
|
||||
If user data is safe, prefer degraded startup over startup failure. If minimum useful functionality can be started safely, start it.
|
||||
|
||||
Startup and schema-migration behavior must be designed for degraded real-world states, including:
|
||||
- legacy schema versions
|
||||
- interrupted migrations
|
||||
- stale temp tables
|
||||
- invalid payloads
|
||||
- duplicates
|
||||
- `NULL` in required columns
|
||||
- partially migrated tables
|
||||
|
||||
## Required Data Classification
|
||||
|
||||
The architecture must explicitly separate:
|
||||
- disposable cache tables
|
||||
- protected user data tables
|
||||
|
||||
Definitions:
|
||||
- Disposable cache tables are read-only, sync-derived, imported, or otherwise rebuildable from a trusted source.
|
||||
- Protected user data tables contain user-authored or otherwise non-rebuildable data.
|
||||
|
||||
Do not mix both classes in one table if recovery semantics differ.
|
||||
|
||||
## Availability Policy For Disposable Data
|
||||
|
||||
For disposable cache tables, availability has priority.
|
||||
|
||||
Rules:
|
||||
- If a table cannot be migrated safely, it may be quarantined, dropped, or recreated empty.
|
||||
- The application must continue startup after such recovery.
|
||||
- The application must restore disposable data through the normal sync, reload, import, or rebuild path.
|
||||
- Recovery must not require manual SQL intervention for routine degraded states.
|
||||
|
||||
## Protection Policy For User Data
|
||||
|
||||
For protected user data, destructive reset is forbidden.
|
||||
|
||||
Rules:
|
||||
- Do not drop, truncate, or recreate protected tables as a recovery shortcut.
|
||||
- Backup-before-change is mandatory, must be performed automatically by the migration engine (never by the operator), and must follow the `backup-management` and `go-database` contracts.
|
||||
- Validate-before-migrate is mandatory.
|
||||
- Migration logic must use fail-safe semantics: stop before applying a risky destructive step when invariants are broken or input is invalid.
|
||||
- The application must emit explicit diagnostics that identify the blocked table, migration step, and reason.
|
||||
|
||||
## Recovery Logic Requirements
|
||||
|
||||
Rules:
|
||||
- Recovery logic must be deterministic.
|
||||
- Recovery logic must be idempotent.
|
||||
- Recovery logic must be retry-safe on every startup.
|
||||
- Recovery logic must be observable through structured logs.
|
||||
- Re-running startup after a partial failure must move the system toward a valid state, not deeper into corruption.
|
||||
|
||||
## Quality Bar
|
||||
|
||||
The application must either:
|
||||
- self-recover and continue startup
|
||||
|
||||
or:
|
||||
|
||||
- stop only when continuing would risk loss or corruption of non-recoverable user data
|
||||
|
||||
Stopping for disposable cache corruption alone is not acceptable when the data can be rebuilt safely.
|
||||
|
||||
If the full feature set cannot be restored safely during startup, the application should start with the minimum safe functionality instead of failing startup, as long as protected user data remains safe.
|
||||
|
||||
## Testing Requirements
|
||||
|
||||
Degraded and legacy states must be tested explicitly, not only happy-path fresh installs.
|
||||
|
||||
Required test coverage includes:
|
||||
- legacy schema upgrades
|
||||
- interrupted migration recovery
|
||||
- partially migrated tables
|
||||
- duplicate rows where uniqueness is expected
|
||||
- `NULL` in required columns
|
||||
- invalid payloads in persisted rows
|
||||
- disposable-table reset and rebuild flow
|
||||
- protected-data migration refusal with explicit diagnostics
|
||||
80
rules/patterns/secret-management/contract.md
Normal file
80
rules/patterns/secret-management/contract.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# Contract: Secret Management
|
||||
|
||||
Version: 1.1
|
||||
|
||||
## Purpose
|
||||
|
||||
Общие правила, которые предотвращают утечку секретов в git, логи, конфиги, шаблоны и release-артефакты.
|
||||
|
||||
## No Secrets In Git
|
||||
|
||||
Secrets must never be committed to the repository, even temporarily.
|
||||
|
||||
This includes:
|
||||
- API keys
|
||||
- access tokens
|
||||
- passwords
|
||||
- DSNs with credentials
|
||||
- private keys
|
||||
- session secrets
|
||||
- OAuth client secrets
|
||||
- `.env` files with real values
|
||||
- production or staging config files with real credentials
|
||||
|
||||
Rules:
|
||||
- Real secrets must never appear in tracked files, commit history, tags, release assets, examples, fixtures, tests, or docs.
|
||||
- `.gitignore` is required for runtime config and local secret files, but `.gitignore` alone is not considered sufficient protection.
|
||||
- Commit only templates and examples with obvious placeholders, for example `CHANGEME`, `example`, or empty strings.
|
||||
- Never place secrets in screenshots, pasted logs, SQL dumps, backups, or exported archives that could later be committed.
|
||||
|
||||
## Where Secrets Live
|
||||
|
||||
Rules:
|
||||
- Store real secrets only in local runtime config, secret stores, environment injection, or deployment-specific configuration outside git.
|
||||
- Keep committed config files secret-free: `config.example.yaml`, `.env.example`, and similar files must contain placeholders only.
|
||||
- If a feature requires a new secret, document the config key name and format, not the real value.
|
||||
|
||||
## Required Git Checks
|
||||
|
||||
Before every commit:
|
||||
- Verify that files with real secrets are gitignored.
|
||||
- Inspect staged changes for secrets, not just working tree files.
|
||||
- Run an automated secret scan against staged content using project tooling or a repository-approved scanner.
|
||||
- If the scan cannot be run, stop and do not commit until an equivalent staged-content check is performed.
|
||||
|
||||
Before every push:
|
||||
- Scan the commits being pushed for secrets again.
|
||||
- Refuse the push if any potential secret is detected until it is reviewed and removed.
|
||||
|
||||
High-risk patterns that must be checked explicitly:
|
||||
- PEM blocks (`BEGIN PRIVATE KEY`, `BEGIN OPENSSH PRIVATE KEY`, `BEGIN RSA PRIVATE KEY`)
|
||||
- tokens in URLs or DSNs
|
||||
- `password=`, `token=`, `secret=`, `apikey=`, `api_key=`
|
||||
- cloud credentials
|
||||
- webhook secrets
|
||||
- JWT signing keys
|
||||
|
||||
## Scheduled Security Audit
|
||||
|
||||
Rules:
|
||||
- Perform a security audit at least once per week.
|
||||
- At least once per week, scan the git repository for leaked secrets, including current files, staged changes, commit history, and reachable tags.
|
||||
- Treat weekly secret scanning as mandatory even if pre-commit and pre-push checks already exist.
|
||||
- If the weekly audit finds a leaked secret, follow the Incident Response rules immediately.
|
||||
|
||||
## Logging and Generated Artifacts
|
||||
|
||||
Rules:
|
||||
- Do not print secrets into terminal output, structured logs, panic messages, or debug dumps.
|
||||
- Do not embed secrets into generated backups, exports, support bundles, or crash reports unless the artifact is explicitly treated as secret operational data and guaranteed to stay outside git.
|
||||
- If secrets must appear in an operational artifact, that artifact inherits the same "never in git" rule as backups.
|
||||
|
||||
## Incident Response
|
||||
|
||||
If a secret is committed or pushed:
|
||||
- Treat it as compromised immediately.
|
||||
- Rotate or revoke the secret.
|
||||
- Remove it from the current tree and from any generated artifacts.
|
||||
- Remove it from all affected commits and from repository history, not just from the latest revision.
|
||||
- Inform the user that history cleanup may be required.
|
||||
- Do not claim safety merely because the repo is private.
|
||||
@@ -1,6 +1,6 @@
|
||||
# Contract: Testing Policy
|
||||
|
||||
Version: 1.0
|
||||
Version: 1.1
|
||||
|
||||
## Purpose
|
||||
|
||||
@@ -17,10 +17,13 @@ Version: 1.0
|
||||
- **Трансформации** — конвертация единиц, нормализация, маппинг полей
|
||||
- **Бизнес-правила** — расчёты, фильтрация, агрегация, приоритизация
|
||||
- **Граничные случаи** — пустой ввод, нулевые значения, переполнение, отсутствующие поля
|
||||
- **Degraded / legacy states** — legacy schema, interrupted migrations, duplicates, invalid persisted rows, partially migrated tables
|
||||
- **Регрессии** — если баг был найден, тест фиксирует его до исправления
|
||||
|
||||
Тест пишется в том же коммите, что и функциональность. Функциональность без теста (там где он обязателен) — неполный коммит.
|
||||
|
||||
Для local-first desktop приложений правила деградированных состояний и recovery-тестов определяются также `local-first-recovery` contract.
|
||||
|
||||
---
|
||||
|
||||
## Когда тест не нужен
|
||||
|
||||
Reference in New Issue
Block a user