From 3d8f193aa306c06a659e15e5bfd45b8d81815092 Mon Sep 17 00:00:00 2001 From: konard Date: Mon, 27 Apr 2026 00:43:53 +0000 Subject: [PATCH 1/3] Initial commit with task details Adding .gitkeep for PR creation (default mode). This file will be removed when the task is complete. Issue: https://github.com/xlabtg/Teleton-Client/issues/29 --- .gitkeep | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitkeep b/.gitkeep index 27c1d38..30c5d03 100644 --- a/.gitkeep +++ b/.gitkeep @@ -1 +1,2 @@ -# .gitkeep file auto-generated at 2026-04-27T00:02:26.981Z for PR creation at branch issue-27-e169ead3bf4d for issue https://github.com/xlabtg/Teleton-Client/issues/27 \ No newline at end of file +# .gitkeep file auto-generated at 2026-04-27T00:02:26.981Z for PR creation at branch issue-27-e169ead3bf4d for issue https://github.com/xlabtg/Teleton-Client/issues/27 +# Updated: 2026-04-27T00:43:53.732Z \ No newline at end of file From 359a7689f6d463e3519209bde08ba570f1f262b0 Mon Sep 17 00:00:00 2001 From: konard Date: Mon, 27 Apr 2026 00:52:20 +0000 Subject: [PATCH 2/3] Add release readiness checklist --- .gitkeep | 2 - BUILD-GUIDE.md | 6 + CONTRIBUTING.md | 1 + README.md | 3 +- docs/release-readiness.md | 56 +++++ docs/release-strategy.md | 6 + scripts/validate-foundation.mjs | 27 ++- scripts/validate-release.mjs | 23 +++ src/foundation/release-readiness.mjs | 298 +++++++++++++++++++++++++++ test/foundation.test.mjs | 5 +- test/release-readiness.test.mjs | 75 +++++++ 11 files changed, 497 insertions(+), 5 deletions(-) delete mode 100644 .gitkeep create mode 100644 docs/release-readiness.md create mode 100644 src/foundation/release-readiness.mjs create mode 100644 test/release-readiness.test.mjs diff --git a/.gitkeep b/.gitkeep deleted file mode 100644 index 30c5d03..0000000 --- a/.gitkeep +++ /dev/null @@ -1,2 +0,0 @@ -# .gitkeep file auto-generated at 2026-04-27T00:02:26.981Z for PR creation at branch issue-27-e169ead3bf4d for issue https://github.com/xlabtg/Teleton-Client/issues/27 -# Updated: 2026-04-27T00:43:53.732Z \ No newline at end of file diff --git a/BUILD-GUIDE.md b/BUILD-GUIDE.md index 1610c3a..d42f44b 100644 --- a/BUILD-GUIDE.md +++ b/BUILD-GUIDE.md @@ -65,6 +65,12 @@ npm run build:debug-artifacts The generated manifests are written to `dist/debug-artifacts/` and are uploaded by `.github/workflows/release-validation.yml`. They record the expected debug artifact paths without using signing secrets. Signed packages must be produced only in the protected `release-signing` environment after human release review. See `docs/release-packaging.md` for the artifact matrix, signing boundary, and publication steps. +## Release Readiness + +Public release is blocked until the checklist in `docs/release-readiness.md` is complete for the reviewed commit. The checklist covers test evidence, license and source publication review, privacy review, security audit evidence, artifact review, documentation completeness, and explicit human release approval. + +Run `npm run validate:release` during release preparation to verify release metadata, artifact documentation, and the machine-readable readiness checklist in `src/foundation/release-readiness.mjs`. Automated validation does not replace the final human approval gate; package publication, app-store submission, signed artifact upload, and release tagging must wait until a human release approver records approval. + ## Input Action Map The shared input action map in `src/platform/action-map.mjs` defines common messaging, Teleton Agent, and TON wallet routes once, then adapts them to desktop shortcuts and mobile gestures. The generated plans include collision reports, reserved mobile system gesture notes, accessibility requirements, and `input.riskyActionBindings.enabled` so risky agent or transaction bindings can be disabled without removing visible workflow controls. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1f4d64e..dac13ac 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -90,6 +90,7 @@ Use these documents as the source of truth for foundation work: - `docs/security-audit.md` for secret scanning, credential rotation, and secure storage review requirements. - `docs/license-matrix.md` for TDLib, Telegram reference client, Teleton Agent, and TON SDK license obligations before release readiness. - `docs/release-packaging.md` for APK, IPA, DMG, EXE, and AppImage artifact targets, public debug manifests, and protected signing boundaries. +- `docs/release-readiness.md` for the final release checklist covering tests, licenses, source publication, privacy, security, artifacts, documentation completeness, and human release approval. - `docs/architecture.md` for planned layers and integration boundaries. - `docs/tdlib-adapter.md` for TDLib adapter and credential handling rules. - `docs/release-strategy.md` for release metadata policy. diff --git a/README.md b/README.md index a404921..6b4bef9 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ This repository is in the foundation phase. The current implementation establish - Upstream license matrix for TDLib, Telegram reference clients, Teleton Agent, and TON SDK release review. - Documented semantic version source of truth and release metadata validation. - Release artifact matrix for APK, IPA, DMG, EXE, and AppImage packaging, with unsigned debug artifact manifests built in public CI and signing reserved for protected environments. +- Release readiness checklist that gates public publication on test evidence, license and source publication review, privacy review, security audit evidence, artifact review, documentation completeness, and human release approval. - Required project documents: `README.md`, `SECURITY.md`, `PRIVACY.md`, `LICENSE`, and `BUILD-GUIDE.md`. ## Quick Start @@ -80,7 +81,7 @@ The project is intended to evolve through these layers: 4. TON blockchain integrations for wallet, transfers, swaps, NFTs, staking, and DNS. 5. Security and privacy controls for credentials, user consent, and auditability. -See `SECURITY.md`, `docs/architecture.md`, `docs/backlog.md`, `docs/tdlib-adapter.md`, `docs/android-wrapper.md`, `docs/ios-wrapper.md`, `docs/desktop-wrapper.md`, `docs/tablet-layout.md`, `docs/web-pwa-wrapper.md`, `docs/security-audit.md`, `docs/license-matrix.md`, `docs/release-strategy.md`, and `docs/release-packaging.md` for the current foundation plan. The agent settings, local runtime, input action map, Android wrapper, iOS wrapper, desktop wrapper, tablet layout, PWA, message database encryption, secure data deletion, security policy, security audit, license matrix, and release packaging sections record the shared settings UI contract, supported runtime directions, platform execution boundaries, shortcut and gesture behavior, hardware security key capability checks, responsive tablet behavior, web installability behavior, vulnerability reporting expectations, credential rotation expectations, secure storage review requirements, upstream license obligations, protected signing boundaries, and remaining native packaging implementation gaps for Android, iOS, desktop, and web wrappers. +See `SECURITY.md`, `docs/architecture.md`, `docs/backlog.md`, `docs/tdlib-adapter.md`, `docs/android-wrapper.md`, `docs/ios-wrapper.md`, `docs/desktop-wrapper.md`, `docs/tablet-layout.md`, `docs/web-pwa-wrapper.md`, `docs/security-audit.md`, `docs/license-matrix.md`, `docs/release-strategy.md`, `docs/release-packaging.md`, and `docs/release-readiness.md` for the current foundation plan. The agent settings, local runtime, input action map, Android wrapper, iOS wrapper, desktop wrapper, tablet layout, PWA, message database encryption, secure data deletion, security policy, security audit, license matrix, release packaging, and release readiness sections record the shared settings UI contract, supported runtime directions, platform execution boundaries, shortcut and gesture behavior, hardware security key capability checks, responsive tablet behavior, web installability behavior, vulnerability reporting expectations, credential rotation expectations, secure storage review requirements, upstream license obligations, source publication review, protected signing boundaries, human release approval, and remaining native packaging implementation gaps for Android, iOS, desktop, and web wrappers. ## Contribution Templates diff --git a/docs/release-readiness.md b/docs/release-readiness.md new file mode 100644 index 0000000..e6e1bda --- /dev/null +++ b/docs/release-readiness.md @@ -0,0 +1,56 @@ +# Release Readiness + +Teleton Client cannot be published publicly from the foundation repository until the release readiness checklist below is completed for the reviewed commit. The checklist is intentionally manual at the final gate: automated validation can prove the repository shape, but a human release approval is required before package publication, app-store submission, signed artifact upload, or release tagging. + +`src/foundation/release-readiness.mjs` is the machine-readable source for this gate. `npm run validate:release` verifies that the checklist and documentation inventory remain present before release readiness is claimed. + +## Release Gate Checklist + +| Gate | Required evidence | Human approver | +| --- | --- | --- | +| Tests and Validation Evidence | Record `npm test`, `npm run validate:secrets`, `npm run audit:security`, `npm run validate:foundation`, `npm run validate:release`, `npm run build:debug-artifacts`, and reviewed changelog check results for the exact commit. | Release manager | +| License and Source Publication Review | Confirm `docs/license-matrix.md` matches shipped dependency versions, source URLs, license texts, notices, local patches, and source publication obligations for GPL, LGPL, unclear-license, and mixed-license inputs. | Legal or release maintainer | +| Privacy Policy and Data Flow Review | Compare `PRIVACY.md` against shipped Telegram, proxy, Teleton Agent, settings sync, notification, and TON behavior. Confirm release notes, screenshots, fixtures, and logs do not expose private message content. | Privacy reviewer | +| Security Audit and Vulnerability Intake Review | Attach `security-audit-report.md`, review `SECURITY.md`, confirm private advisory intake, coordinated disclosure, credential rotation, secure storage, diagnostics redaction, and CODEOWNERS review status. | Security maintainer | +| Release Artifact and Signing Review | Attach unsigned public CI debug manifests for Android, iOS, macOS, Windows, and Linux. Confirm signed artifacts are built only from reviewed commits inside the protected `release-signing` environment. | Release manager | +| Documentation Completeness Review | Compare shipped foundation modules and tests against README, BUILD-GUIDE, SECURITY, PRIVACY, architecture, release strategy, packaging, security audit, and license documentation. Current behavior must not be overstated as production behavior. | Documentation owner | +| Human Release Approval | Record explicit human release approval only after every checklist item is complete. Publication, tags, app-store submission, and signed artifact upload stay blocked until this approval is recorded. | Human release approver | + +## Documentation Completeness + +Documentation is considered release-ready only when it matches the behavior present in the reviewed commit: + +- Current behavior must be documented in the same pull request that adds or changes it. +- Planned behavior must be labeled as future work when no implementation exists yet. +- Security, privacy, release automation, platform contracts, and user-visible workflows must link to the documents reviewers are expected to inspect. +- Validation coverage must include either a focused test, release validation rule, foundation validation rule, or an explicit manual review item. +- Screenshots, logs, fixtures, and release notes must be redacted before they are attached to review records. + +## Source Publication Requirements + +Before public release, reviewers must confirm that every distributed dependency, bundled binary, native library, WebAssembly module, generated SDK, copied reference asset, and local patch has a release record. The record must include the exact version or commit, source URL, license identifier, license text, notice requirements, and source publication decision. + +Copyleft and unclear-license inputs remain release-blocking until a human legal reviewer approves the exact reuse model. Reference-only Telegram clients, GPL or LGPL code, and mixed-license repositories must not be copied into distributed artifacts without a written compliance plan. + +## Current Behavior Inventory + +| Behavior group | Source of truth | Validation | Release documentation | +| --- | --- | --- | --- | +| Release metadata | `src/foundation/release-metadata.mjs` | `test/release-metadata.test.mjs` | `docs/release-strategy.md`, `BUILD-GUIDE.md` | +| Release artifacts | `src/foundation/release-artifacts.mjs` | `test/release-artifacts.test.mjs` | `docs/release-packaging.md`, `BUILD-GUIDE.md` | +| Release readiness | `src/foundation/release-readiness.mjs` | `test/release-readiness.test.mjs` | `docs/release-readiness.md` | +| Security audit | `src/foundation/security-audit.mjs` | `test/security-audit-report.test.mjs` | `docs/security-audit.md` | +| Secret audit | `src/foundation/secret-audit.mjs` | `test/secret-audit.test.mjs` | `docs/security-audit.md` | +| License matrix | `docs/license-matrix.md` | `test/license-compliance.test.mjs` | `docs/license-matrix.md` | +| Privacy policy | `PRIVACY.md` | `test/privacy-policy.test.mjs` | `PRIVACY.md` | +| TDLib adapter | `src/tdlib/client-adapter.mjs` | `test/tdlib-adapter.test.mjs` | `docs/tdlib-adapter.md` | +| Message database storage | `src/tdlib/message-database-storage.mjs` | `test/message-database-storage.test.mjs` | `docs/architecture.md` | +| Settings model | `src/foundation/settings-model.mjs` | `test/settings-model.test.mjs` | `README.md` | +| Proxy connectivity | `src/foundation/proxy-manager.mjs` | `test/proxy-manager.test.mjs` | `README.md` | +| Agent settings | `src/foundation/agent-settings-view.mjs` | `test/agent-settings-view.test.mjs` | `docs/architecture.md` | +| Agent runtime | `src/foundation/agent-runtime-supervisor.mjs` | `test/agent-runtime-supervisor.test.mjs` | `README.md` | +| TON wallet | `src/ton/wallet-adapter.mjs` | `test/ton-adapter.test.mjs` | `README.md` | +| Android wrapper | `src/platform/android-wrapper.mjs` | `test/android-wrapper.test.mjs` | `docs/android-wrapper.md` | +| E2E workflow harness | `src/foundation/e2e-workflow-harness.mjs` | `test/e2e-workflow-harness.test.mjs` | `BUILD-GUIDE.md` | + +This inventory is not the full product roadmap. It is the release-review slice that proves current foundation behavior is documented, tested, and separated from future production implementation claims. diff --git a/docs/release-strategy.md b/docs/release-strategy.md index 09a7d6e..e8c2c95 100644 --- a/docs/release-strategy.md +++ b/docs/release-strategy.md @@ -16,6 +16,12 @@ The package remains private until a reviewed release workflow is introduced. Pul See `docs/release-packaging.md` for the artifact paths, runner matrix, protected signing boundary, and publication checklist. Pull requests do not receive signing secrets; signed packages must be produced only from reviewed commits inside the protected `release-signing` environment. +## Release Readiness Gate + +`docs/release-readiness.md` is the final source publication, documentation completeness, and release approval checklist. Before public release, a human release approver must confirm test evidence, license and source publication review, privacy review, security audit evidence, artifact review, documentation completeness, and protected signing status for the exact commit being published. + +`npm run validate:release` verifies the machine-readable checklist in `src/foundation/release-readiness.mjs`, but automation does not approve a public release. Package publication, release tags, signed artifact uploads, and app-store submissions remain blocked until the human release approval is recorded in the release review. + ## Semantic Versioning Versions must use stable semantic version format: `MAJOR.MINOR.PATCH`. diff --git a/scripts/validate-foundation.mjs b/scripts/validate-foundation.mjs index 4dcd52d..d2eb884 100644 --- a/scripts/validate-foundation.mjs +++ b/scripts/validate-foundation.mjs @@ -25,6 +25,7 @@ const requiredFiles = [ 'docs/architecture.md', 'docs/release-strategy.md', 'docs/release-packaging.md', + 'docs/release-readiness.md', 'docs/security-audit.md', 'docs/license-matrix.md', 'docs/backlog.md', @@ -43,7 +44,9 @@ const requiredFiles = [ 'test/agent-plugin-registry.test.mjs', 'src/foundation/release-artifacts.mjs', 'scripts/build-debug-artifacts.mjs', - 'test/release-artifacts.test.mjs' + 'test/release-artifacts.test.mjs', + 'src/foundation/release-readiness.mjs', + 'test/release-readiness.test.mjs' ]; for (const requiredFile of requiredFiles) { @@ -146,6 +149,7 @@ const requiredContributingPatterns = [ /PRIVACY\.md/, /docs\/license-matrix\.md/, /docs\/release-packaging\.md/, + /docs\/release-readiness\.md/, /secrets/i, /credentials/i, /Telegram API IDs or hashes/i, @@ -269,6 +273,26 @@ for (const pattern of requiredLicenseMatrixPatterns) { assert.match(licenseMatrix, pattern, `docs/license-matrix.md must include ${pattern}`); } +const releaseReadiness = await readFile(new URL('docs/release-readiness.md', root), 'utf8'); +const requiredReleaseReadinessPatterns = [ + /Tests and Validation Evidence/i, + /License and Source Publication Review/i, + /Privacy Policy and Data Flow Review/i, + /Security Audit and Vulnerability Intake Review/i, + /Release Artifact and Signing Review/i, + /Documentation Completeness Review/i, + /Human Release Approval/i, + /source publication/i, + /human release approval/i, + /npm run validate:release/, + /release-signing/, + /Current Behavior Inventory/i +]; + +for (const pattern of requiredReleaseReadinessPatterns) { + assert.match(releaseReadiness, pattern, `docs/release-readiness.md must include ${pattern}`); +} + const docsToScan = [ 'README.md', 'CONTRIBUTING.md', @@ -277,6 +301,7 @@ const docsToScan = [ 'BUILD-GUIDE.md', 'docs/architecture.md', 'docs/security-audit.md', + 'docs/release-readiness.md', 'docs/license-matrix.md', 'docs/tdlib-adapter.md' ]; diff --git a/scripts/validate-release.mjs b/scripts/validate-release.mjs index f665f21..6df00f2 100644 --- a/scripts/validate-release.mjs +++ b/scripts/validate-release.mjs @@ -4,12 +4,18 @@ import { readFile } from 'node:fs/promises'; import { RELEASE_METADATA, VERSION_SOURCE_OF_TRUTH, isStableSemver } from '../src/foundation/release-metadata.mjs'; import { assertReleaseArtifactMatrix, listReleaseArtifactTargets } from '../src/foundation/release-artifacts.mjs'; +import { + assertReleaseReadinessChecklist, + listReleaseDocumentationInventory, + listReleaseReadinessChecklist +} from '../src/foundation/release-readiness.mjs'; const root = new URL('../', import.meta.url); const packageJson = JSON.parse(await readFile(new URL('package.json', root), 'utf8')); const changelog = await readFile(new URL('CHANGELOG.md', root), 'utf8'); const releaseWorkflow = await readFile(new URL('.github/workflows/release-validation.yml', root), 'utf8'); const releasePackaging = await readFile(new URL('docs/release-packaging.md', root), 'utf8'); +const releaseReadiness = await readFile(new URL('docs/release-readiness.md', root), 'utf8'); assert.equal(VERSION_SOURCE_OF_TRUTH, 'package.json', 'package.json must be the documented version source of truth'); assert.equal(RELEASE_METADATA.sourceOfTruth, VERSION_SOURCE_OF_TRUTH, 'release metadata must name its source of truth'); @@ -26,6 +32,7 @@ assert.equal( 'package.json must expose the public debug artifact manifest build command' ); assertReleaseArtifactMatrix(); +assertReleaseReadinessChecklist(); assert.match(releaseWorkflow, /debug-artifacts:/, 'release workflow must build debug artifact manifests'); assert.match(releaseWorkflow, /npm run build:debug-artifacts/, 'release workflow must run the debug artifact builder'); assert.match(releaseWorkflow, /actions\/upload-artifact@v4/, 'release workflow must upload debug artifact manifests'); @@ -38,4 +45,20 @@ for (const target of listReleaseArtifactTargets()) { assert.match(releasePackaging, new RegExp(target.debugBuild.id, 'i'), `${target.debugBuild.id} must be documented`); } +assert.match(releaseReadiness, /^# Release Readiness$/m, 'release readiness documentation must exist'); +assert.match(releaseReadiness, /human release approval/i, 'release readiness must require human approval'); +assert.match(releaseReadiness, /source publication/i, 'release readiness must cover source publication obligations'); +assert.match(releaseReadiness, /Documentation Completeness/i, 'release readiness must cover documentation completeness'); + +for (const item of listReleaseReadinessChecklist()) { + assert.match(releaseReadiness, new RegExp(item.title.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i')); +} + +for (const entry of listReleaseDocumentationInventory()) { + const sourcePattern = entry.source.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + const testPattern = entry.test.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + assert.match(releaseReadiness, new RegExp(sourcePattern), `${entry.source} must appear in release readiness docs`); + assert.match(releaseReadiness, new RegExp(testPattern), `${entry.test} must appear in release readiness docs`); +} + console.log(`Release validation passed for ${packageJson.name}@${packageJson.version}.`); diff --git a/src/foundation/release-readiness.mjs b/src/foundation/release-readiness.mjs new file mode 100644 index 0000000..67d113d --- /dev/null +++ b/src/foundation/release-readiness.mjs @@ -0,0 +1,298 @@ +export const RELEASE_READINESS_REQUIRED_IDS = Object.freeze([ + 'tests', + 'licenses', + 'privacy', + 'security', + 'artifacts', + 'documentation', + 'human-release-approval' +]); + +const RELEASE_READINESS_CHECKLIST = Object.freeze([ + { + id: 'tests', + title: 'Tests and Validation Evidence', + requiredBeforePublicRelease: true, + humanApproverRole: 'release manager', + evidence: [ + '`npm test` result for the reviewed commit.', + '`npm run validate:secrets`, `npm run audit:security`, `npm run validate:foundation`, and `npm run validate:release` results.', + '`npm run build:debug-artifacts` output or CI artifacts for every supported debug target.', + '`npm run changelog:check` result after generated release notes are reviewed.' + ], + documents: ['BUILD-GUIDE.md', 'docs/release-strategy.md'] + }, + { + id: 'licenses', + title: 'License and Source Publication Review', + requiredBeforePublicRelease: true, + humanApproverRole: 'legal or release maintainer', + evidence: [ + 'Reviewed `docs/license-matrix.md` for exact shipped dependency versions, source URLs, license texts, and local patches.', + 'Confirmed source publication obligations for GPL, LGPL, unclear-license, and mixed-license inputs.', + 'Attached third-party notice and source-publication decisions to the private release record.' + ], + documents: ['LICENSE', 'docs/license-matrix.md'] + }, + { + id: 'privacy', + title: 'Privacy Policy and Data Flow Review', + requiredBeforePublicRelease: true, + humanApproverRole: 'privacy reviewer', + evidence: [ + 'Reviewed `PRIVACY.md` against shipped Telegram, proxy, agent, sync, notification, and TON behavior.', + 'Confirmed screenshots, release notes, fixtures, and logs contain no private message content.', + 'Confirmed cloud-capable behavior still requires explicit opt-in and user-visible approval gates.' + ], + documents: ['PRIVACY.md', 'docs/architecture.md'] + }, + { + id: 'security', + title: 'Security Audit and Vulnerability Intake Review', + requiredBeforePublicRelease: true, + humanApproverRole: 'security maintainer', + evidence: [ + 'Attached `security-audit-report.md` generated by `npm run audit:security -- --output security-audit-report.md`.', + 'Reviewed `SECURITY.md` private advisory intake, coordinated disclosure, and supported-version guidance.', + 'Confirmed credential rotation, secure storage, diagnostics redaction, and CODEOWNERS review status.' + ], + documents: ['SECURITY.md', 'docs/security-audit.md', '.github/CODEOWNERS'] + }, + { + id: 'artifacts', + title: 'Release Artifact and Signing Review', + requiredBeforePublicRelease: true, + humanApproverRole: 'release manager', + evidence: [ + 'Attached unsigned public CI debug artifact manifests for Android, iOS, macOS, Windows, and Linux.', + 'Confirmed signed packages are produced only from reviewed commits in the protected `release-signing` environment.', + 'Recorded platform signing, notarization, timestamping, or optional AppImage signature evidence.' + ], + documents: ['docs/release-packaging.md', '.github/workflows/release-validation.yml'] + }, + { + id: 'documentation', + title: 'Documentation Completeness Review', + requiredBeforePublicRelease: true, + humanApproverRole: 'documentation owner', + evidence: [ + 'Compared shipped foundation modules and tests against README, BUILD-GUIDE, SECURITY, PRIVACY, and docs entries.', + 'Confirmed new user-visible behavior, release behavior, security behavior, and platform contracts are documented in the same pull request.', + 'Confirmed stale planned behavior is labeled as future work and current behavior is not overstated.' + ], + documents: ['README.md', 'BUILD-GUIDE.md', 'docs/architecture.md', 'docs/release-readiness.md'] + }, + { + id: 'human-release-approval', + title: 'Human Release Approval', + requiredBeforePublicRelease: true, + humanApproverRole: 'human release approver', + evidence: [ + 'Recorded explicit approval from a human maintainer after every checklist item is complete.', + 'Confirmed package publication, app-store submission, release tagging, and signed artifact upload stay blocked until that approval is recorded.', + 'Linked approval evidence from the private or protected release record.' + ], + documents: ['docs/release-readiness.md', 'docs/release-strategy.md'] + } +]); + +const RELEASE_DOCUMENTATION_INVENTORY = Object.freeze([ + { + id: 'release-metadata', + source: 'src/foundation/release-metadata.mjs', + test: 'test/release-metadata.test.mjs', + docs: [ + { path: 'docs/release-strategy.md', pattern: /package\.json.*single source of truth/i }, + { path: 'BUILD-GUIDE.md', pattern: /package\.json.*only version source of truth/i } + ] + }, + { + id: 'release-artifacts', + source: 'src/foundation/release-artifacts.mjs', + test: 'test/release-artifacts.test.mjs', + docs: [ + { path: 'docs/release-packaging.md', pattern: /Artifact Matrix/i }, + { path: 'BUILD-GUIDE.md', pattern: /Release Packaging/i } + ] + }, + { + id: 'release-readiness', + source: 'src/foundation/release-readiness.mjs', + test: 'test/release-readiness.test.mjs', + docs: [{ path: 'docs/release-readiness.md', pattern: /Current Behavior Inventory/i }] + }, + { + id: 'security-audit', + source: 'src/foundation/security-audit.mjs', + test: 'test/security-audit-report.test.mjs', + docs: [{ path: 'docs/security-audit.md', pattern: /Release Audit Report/i }] + }, + { + id: 'secret-audit', + source: 'src/foundation/secret-audit.mjs', + test: 'test/secret-audit.test.mjs', + docs: [{ path: 'docs/security-audit.md', pattern: /Automated Secret Scan/i }] + }, + { + id: 'license-matrix', + source: 'docs/license-matrix.md', + test: 'test/license-compliance.test.mjs', + docs: [{ path: 'docs/license-matrix.md', pattern: /source publication/i }] + }, + { + id: 'privacy-policy', + source: 'PRIVACY.md', + test: 'test/privacy-policy.test.mjs', + docs: [{ path: 'PRIVACY.md', pattern: /Data Flow Coverage/i }] + }, + { + id: 'tdlib-adapter', + source: 'src/tdlib/client-adapter.mjs', + test: 'test/tdlib-adapter.test.mjs', + docs: [{ path: 'docs/tdlib-adapter.md', pattern: /TDLib Adapter Boundary/i }] + }, + { + id: 'message-database-storage', + source: 'src/tdlib/message-database-storage.mjs', + test: 'test/message-database-storage.test.mjs', + docs: [{ path: 'docs/architecture.md', pattern: /message database encryption/i }] + }, + { + id: 'settings-model', + source: 'src/foundation/settings-model.mjs', + test: 'test/settings-model.test.mjs', + docs: [{ path: 'README.md', pattern: /Shared cross-platform settings model/i }] + }, + { + id: 'proxy-connectivity', + source: 'src/foundation/proxy-manager.mjs', + test: 'test/proxy-manager.test.mjs', + docs: [{ path: 'README.md', pattern: /ProxyManager route selection/i }] + }, + { + id: 'agent-settings', + source: 'src/foundation/agent-settings-view.mjs', + test: 'test/agent-settings-view.test.mjs', + docs: [{ path: 'docs/architecture.md', pattern: /Agent settings UI shells/i }] + }, + { + id: 'agent-runtime', + source: 'src/foundation/agent-runtime-supervisor.mjs', + test: 'test/agent-runtime-supervisor.test.mjs', + docs: [{ path: 'README.md', pattern: /Local Teleton Agent runtime supervisor/i }] + }, + { + id: 'ton-wallet', + source: 'src/ton/wallet-adapter.mjs', + test: 'test/ton-adapter.test.mjs', + docs: [{ path: 'README.md', pattern: /TON wallet adapter contract/i }] + }, + { + id: 'android-wrapper', + source: 'src/platform/android-wrapper.mjs', + test: 'test/android-wrapper.test.mjs', + docs: [{ path: 'docs/android-wrapper.md', pattern: /Android Wrapper/i }] + }, + { + id: 'e2e-workflow-harness', + source: 'src/foundation/e2e-workflow-harness.mjs', + test: 'test/e2e-workflow-harness.test.mjs', + docs: [{ path: 'BUILD-GUIDE.md', pattern: /End-to-End Workflow Checks/i }] + } +]); + +function clone(value) { + return structuredClone(value); +} + +export function listReleaseReadinessChecklist() { + return clone(RELEASE_READINESS_CHECKLIST); +} + +export function listReleaseDocumentationInventory() { + return clone(RELEASE_DOCUMENTATION_INVENTORY); +} + +export function validateReleaseReadinessChecklist(checklist = RELEASE_READINESS_CHECKLIST) { + const errors = []; + + if (!Array.isArray(checklist)) { + return ['Release readiness checklist must be an array.']; + } + + const ids = checklist.map((item) => item.id); + if (JSON.stringify(ids) !== JSON.stringify(RELEASE_READINESS_REQUIRED_IDS)) { + errors.push(`Release readiness checklist must include ${RELEASE_READINESS_REQUIRED_IDS.join(', ')} in order.`); + } + + for (const item of checklist) { + const label = item?.id ?? ''; + + if (item?.requiredBeforePublicRelease !== true) { + errors.push(`${label} must be required before public release.`); + } + + if (!item?.humanApproverRole) { + errors.push(`${label} must name a human approver role.`); + } + + if (!Array.isArray(item?.evidence) || item.evidence.length === 0) { + errors.push(`${label} must list release review evidence.`); + } + + if (!Array.isArray(item?.documents) || item.documents.length === 0) { + errors.push(`${label} must link release review documents.`); + } + } + + return errors; +} + +export function validateReleaseDocumentationInventory(inventory = RELEASE_DOCUMENTATION_INVENTORY) { + const errors = []; + + if (!Array.isArray(inventory)) { + return ['Release documentation inventory must be an array.']; + } + + for (const entry of inventory) { + const label = entry?.id ?? ''; + + if (!entry?.source) { + errors.push(`${label} must declare the source of truth.`); + } + + if (!entry?.test) { + errors.push(`${label} must declare validation coverage.`); + } + + if (!Array.isArray(entry?.docs) || entry.docs.length === 0) { + errors.push(`${label} must declare documentation coverage.`); + continue; + } + + for (const doc of entry.docs) { + if (!doc?.path || !(doc.pattern instanceof RegExp)) { + errors.push(`${label} documentation entries must include a path and RegExp pattern.`); + } + } + } + + return errors; +} + +export function assertReleaseReadinessChecklist({ + checklist = RELEASE_READINESS_CHECKLIST, + inventory = RELEASE_DOCUMENTATION_INVENTORY +} = {}) { + const errors = [ + ...validateReleaseReadinessChecklist(checklist), + ...validateReleaseDocumentationInventory(inventory) + ]; + + if (errors.length > 0) { + throw new Error(`Invalid release readiness checklist:\n- ${errors.join('\n- ')}`); + } + + return true; +} diff --git a/test/foundation.test.mjs b/test/foundation.test.mjs index d034997..525a6bc 100644 --- a/test/foundation.test.mjs +++ b/test/foundation.test.mjs @@ -32,13 +32,16 @@ test('foundation artifacts required by issue 1 are present', () => { 'config/epic-subtasks.json', 'docs/release-strategy.md', 'docs/release-packaging.md', + 'docs/release-readiness.md', 'docs/security-audit.md', 'docs/license-matrix.md', 'docs/contributing-templates.md', 'docs/tdlib-adapter.md', 'src/foundation/security-audit.mjs', + 'src/foundation/release-readiness.mjs', 'scripts/audit-security.mjs', - 'test/security-audit-report.test.mjs' + 'test/security-audit-report.test.mjs', + 'test/release-readiness.test.mjs' ]; for (const requiredFile of requiredFiles) { diff --git a/test/release-readiness.test.mjs b/test/release-readiness.test.mjs new file mode 100644 index 0000000..7e51180 --- /dev/null +++ b/test/release-readiness.test.mjs @@ -0,0 +1,75 @@ +import assert from 'node:assert/strict'; +import { existsSync } from 'node:fs'; +import { readFile } from 'node:fs/promises'; +import { test } from 'node:test'; + +const root = new URL('../', import.meta.url); + +test('release readiness checklist covers required publication gates and human approval', async () => { + const readiness = await import('../src/foundation/release-readiness.mjs'); + const checklist = readiness.listReleaseReadinessChecklist(); + + assert.deepEqual( + checklist.map((item) => item.id), + [ + 'tests', + 'licenses', + 'privacy', + 'security', + 'artifacts', + 'documentation', + 'human-release-approval' + ] + ); + + for (const item of checklist) { + assert.equal(item.requiredBeforePublicRelease, true, `${item.id} must block public release`); + assert.ok(item.humanApproverRole, `${item.id} must name a human approver role`); + assert.ok(item.evidence.length > 0, `${item.id} must list release evidence`); + } + + assert.doesNotThrow(() => readiness.assertReleaseReadinessChecklist()); +}); + +test('release readiness documentation records source publication and shipped behavior review', async () => { + const readinessDoc = await readFile(new URL('docs/release-readiness.md', root), 'utf8'); + const readiness = await import('../src/foundation/release-readiness.mjs'); + + assert.match(readinessDoc, /^# Release Readiness$/m); + assert.match(readinessDoc, /source publication/i); + assert.match(readinessDoc, /human release approval/i); + assert.match(readinessDoc, /Documentation Completeness/i); + + for (const item of readiness.listReleaseReadinessChecklist()) { + assert.match(readinessDoc, new RegExp(item.title.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i')); + } +}); + +test('release documentation inventory maps shipped foundation behavior to docs and tests', async () => { + const readiness = await import('../src/foundation/release-readiness.mjs'); + const inventory = readiness.listReleaseDocumentationInventory(); + + assert.ok(inventory.length >= 10, 'release inventory should cover shipped foundation behavior groups'); + + for (const entry of inventory) { + assert.equal(existsSync(new URL(entry.source, root)), true, `${entry.id} source must exist`); + assert.equal(existsSync(new URL(entry.test, root)), true, `${entry.id} test must exist`); + + for (const doc of entry.docs) { + const content = await readFile(new URL(doc.path, root), 'utf8'); + assert.match(content, doc.pattern, `${entry.id} must be documented in ${doc.path}`); + } + } +}); + +test('release validation enforces the readiness checklist', async () => { + const packageJson = JSON.parse(await readFile(new URL('package.json', root), 'utf8')); + const releaseValidation = await readFile(new URL('scripts/validate-release.mjs', root), 'utf8'); + const releaseStrategy = await readFile(new URL('docs/release-strategy.md', root), 'utf8'); + const buildGuide = await readFile(new URL('BUILD-GUIDE.md', root), 'utf8'); + + assert.equal(packageJson.scripts['validate:release'], 'node scripts/validate-release.mjs'); + assert.match(releaseValidation, /assertReleaseReadinessChecklist/); + assert.match(releaseStrategy, /docs\/release-readiness\.md/); + assert.match(buildGuide, /docs\/release-readiness\.md/); +}); From 651b65ca85c66ff9b8832c9e31ff81600211ab3c Mon Sep 17 00:00:00 2001 From: konard Date: Mon, 27 Apr 2026 00:56:21 +0000 Subject: [PATCH 3/3] Revert: Remove .gitkeep changes from initial commit --- .gitkeep | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitkeep diff --git a/.gitkeep b/.gitkeep new file mode 100644 index 0000000..27c1d38 --- /dev/null +++ b/.gitkeep @@ -0,0 +1 @@ +# .gitkeep file auto-generated at 2026-04-27T00:02:26.981Z for PR creation at branch issue-27-e169ead3bf4d for issue https://github.com/xlabtg/Teleton-Client/issues/27 \ No newline at end of file