From 75280517f2770d75444e0c777eacdba065e27c58 Mon Sep 17 00:00:00 2001 From: SMOKAHONTAS <69312778+bayyubenjamin@users.noreply.github.com> Date: Thu, 2 Jul 2026 23:11:04 +0700 Subject: [PATCH 01/11] docs: improve developer onboarding --- README.md | 128 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 103 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index aadb464f..0c58bd08 100644 --- a/README.md +++ b/README.md @@ -2,26 +2,31 @@ [![CI](https://github.com/bayyubenjamin/stacksone/actions/workflows/clarinet.yaml/badge.svg)](https://github.com/bayyubenjamin/stacksone/actions/workflows/clarinet.yaml) [![npm](https://img.shields.io/npm/v/@bayybays/stacksone-sdk)](https://www.npmjs.com/package/@bayybays/stacksone-sdk) ![Stacks](https://img.shields.io/badge/network-Stacks-5546FF?logo=stacks) ![License](https://img.shields.io/badge/license-MIT-2ea44f) -StacksOne is a modular identity, progression, mission, badge, token, leaderboard, and engagement layer built on Stacks. The repository contains a React reference application, the `@bayybays/stacksone-sdk` package, wallet integration, and a Clarinet smart-contract workspace. +StacksOne is a modular identity, progression, mission, badge, token, leaderboard, reputation, and engagement layer built on Stacks. This repository contains: -## Product flow +- a React reference application; +- the published `@bayybays/stacksone-sdk` package; +- browser wallet and contract integrations; +- a Clarinet workspace for the contract sources included in this repository; +- tests and operational documentation. + +## What StacksOne does + +StacksOne gives a Stacks application a reusable progression model: ```text Connect wallet → read profile → complete mission → submit transaction → wait for confirmation → earn XP → unlock badges → build reputation ``` -Wallet request, transaction submission, and confirmed chain state are treated as separate stages. The UI keeps writes pending until the expected state can be read on-chain. +Wallet approval, transaction submission, and confirmed on-chain state are separate stages. A wallet callback means a transaction was submitted. It does not mean the expected state change is already confirmed. -## Repository +## Requirements -| Path | Purpose | -|---|---| -| `src/` | Home, Tasks, Vault, Profile, and Gaming UI | -| `sdk/` | Client, contract registry, network, and value helpers | -| `smart-contracts/` | Clarity sources, Clarinet manifest, and Simnet tests | -| `tests/` | Public SDK behavior tests | -| `docs/` | SDK, architecture, workflow, contract, and security notes | +- Node.js `>=18.18`; +- npm with lockfile support; +- a browser Stacks wallet for interactive writes; +- Clarinet tooling only when developing or deploying Clarity contracts. ## Quick start @@ -33,49 +38,122 @@ cp .env.example .env npm run dev ``` -Supabase values are optional. Run quality checks with: +The Supabase values in `.env` are optional. Leave them empty to run the wallet and on-chain features without the supporting cache layer. + +Run the complete repository checks: ```bash npm test npm run build npm pack --dry-run -cd smart-contracts && npm ci && npm test + +cd smart-contracts +npm ci +npm test ``` -## SDK +## SDK quick example ```js import { StacksOneClient } from '@bayybays/stacksone-sdk'; const client = new StacksOneClient({ network: 'mainnet' }); + const stats = await client.getUserStats(address); -const balance = await client.getTokenBalance(address, 'one'); +const oneBalance = await client.getTokenBalance(address, 'one'); const taskDone = await client.isTaskDone(address, 101); ``` -Read [SDK Quick Start](docs/SDK_QUICKSTART.md) and [SDK API Reference](docs/SDK_API.md). +The current `2.x` SDK is intentionally read-oriented. It provides normalized protocol reads, registries, helpers, and browser wallet connection. Contract writes in the reference application use `openContractCall` directly so transaction arguments, post conditions, and confirmation behavior remain explicit. + +Read [SDK Quick Start](docs/SDK_QUICKSTART.md), [SDK API Reference](docs/SDK_API.md), and [Write Transactions](docs/WRITE_TRANSACTIONS.md). + +## Repository map + +| Path | Purpose | +|---|---| +| `src/` | Reference UI for Home, Tasks, Vault, Profile, and Gaming experiences | +| `sdk/` | Public client, canonical contract registry, network resolver, and value helpers | +| `smart-contracts/` | Clarity sources included in this repository, Clarinet manifest, and Simnet tests | +| `tests/` | Public SDK behavior and package-entrypoint tests | +| `docs/` | Architecture, contract inventory, transactions, deployment, workflow, and security guidance | + +## Contract surfaces + +The runtime registry and the local Clarinet workspace serve different purposes: + +- `sdk/contracts.js` is the canonical application and SDK registry for configured mainnet contracts; +- `smart-contracts/Clarinet.toml` describes only the contract sources currently included in the local Clarinet workspace; +- a contract can be configured on mainnet without its historical source being registered in this workspace; +- a local contract can be experimental and not yet configured for the application. + +Configured mainnet deployer: + +```text +SP3GHKMV4GSYNA8WGBX83DACG80K1RRVQZAZMB9J3 +``` + +Configured runtime contracts: + +```text +genesis-core-v10 +genesis-missions-v10 +genesis-badges-v10 +genesis-leaderboard-v1 +genesis-boost-v1 +chaintap +token-poin +token-one +``` + +See [Contract Inventory](docs/CONTRACTS.md) for the exact local-versus-mainnet status and compatibility rules. + +## Architecture + +```text +React reference application + ↓ +StacksOne SDK + canonical registry + ↓ +Stacks API reads + browser wallet submissions + ↓ +Configured Clarity contracts +``` -## Configured mainnet contracts +Confirmed on-chain records are authoritative. Supabase is optional and must remain a supporting cache or indexing layer. Frontend validation improves user experience but never replaces contract authorization. -Deployer: `SP3GHKMV4GSYNA8WGBX83DACG80K1RRVQZAZMB9J3` +See [System Architecture](docs/SYSTEM_ARCHITECTURE.md). -`genesis-core-v10` · `genesis-missions-v10` · `genesis-badges-v10` · `genesis-leaderboard-v1` · `genesis-boost-v1` · `chaintap` · `token-poin` · `token-one` +## Documentation -Application code imports these identifiers from `sdk/contracts.js` to prevent configuration drift. +| Document | Use it for | +|---|---| +| [SDK Quick Start](docs/SDK_QUICKSTART.md) | Installing the package and reading protocol state | +| [SDK API Reference](docs/SDK_API.md) | Method signatures, return values, errors, and advanced injection options | +| [Contract Inventory](docs/CONTRACTS.md) | Understanding runtime contracts and the local Clarinet workspace | +| [Write Transactions](docs/WRITE_TRANSACTIONS.md) | Building confirmation-safe browser contract calls | +| [Deployment Guide](docs/DEPLOYMENT.md) | Releasing contracts, registry changes, the SDK, and the frontend | +| [Development Workflow](docs/WORKFLOW.md) | Changing code in the correct order and running quality gates | +| [System Architecture](docs/SYSTEM_ARCHITECTURE.md) | Data ownership, module boundaries, and transaction lifecycle | +| [Security Policy](docs/SECURITY.md) | Reporting issues, trust boundaries, and known limitations | ## Engineering principles - On-chain records remain authoritative. - Frontend checks do not replace contract authorization. -- Submitted transactions remain pending until confirmed state is readable. -- Supabase is optional and used only as a supporting layer. -- Contract changes require explicit versioning and migration. +- Submitted writes remain pending until confirmed state is readable. +- Contract identifiers are imported from `sdk/contracts.js` rather than duplicated. +- Supabase remains optional and secondary to chain state. +- Contract logic changes require explicit versioning and migration documentation. +- SDK behavior changes require public tests and documentation updates. + +## Security status -See [Development Workflow](docs/WORKFLOW.md), [System Architecture](docs/SYSTEM_ARCHITECTURE.md), and [Security Policy](docs/SECURITY.md). +StacksOne has not completed an independent third-party audit. Administrative operations still require a documented multisig process, and deployed contract logic must be replaced with a new version when behavior changes. Review [Security Policy](docs/SECURITY.md) before production integration. ## Roadmap -TypeScript declarations, React hooks, richer confirmation feedback, dedicated activity views, contract-controlled mission rewards, multisig operations, migration playbooks, and expanded integration examples. +Planned improvements include TypeScript declarations, React hooks, richer confirmation feedback, dedicated activity views, contract-controlled mission rewards, multisig operations, migration playbooks, and expanded integration examples. ## License From f6fb06bafa165470154557c823d2f2bbcd97c4b0 Mon Sep 17 00:00:00 2001 From: SMOKAHONTAS <69312778+bayyubenjamin@users.noreply.github.com> Date: Thu, 2 Jul 2026 23:11:27 +0700 Subject: [PATCH 02/11] docs: document contract inventory --- docs/CONTRACTS.md | 93 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 docs/CONTRACTS.md diff --git a/docs/CONTRACTS.md b/docs/CONTRACTS.md new file mode 100644 index 00000000..06e1bd0a --- /dev/null +++ b/docs/CONTRACTS.md @@ -0,0 +1,93 @@ +# Contract Inventory + +This document separates the contracts configured for the running application from the contract sources included in the local Clarinet workspace. They are related, but they are not the same inventory. + +## Sources of truth + +| Concern | Source of truth | +|---|---| +| Contracts used by the SDK and reference application | `sdk/contracts.js` | +| Contract sources compiled and tested by the local Clarinet workspace | `smart-contracts/Clarinet.toml` | +| Confirmed user state and asset ownership | The deployed Clarity contracts | +| Optional indexed or cached data | Supabase, never authoritative | + +Do not infer that a mainnet contract is missing merely because its source is not registered in the current Clarinet manifest. Do not infer that a local contract is live merely because its source exists in this repository. + +## Configured mainnet registry + +The canonical runtime deployer is: + +```text +SP3GHKMV4GSYNA8WGBX83DACG80K1RRVQZAZMB9J3 +``` + +| Registry key | Contract name | Runtime role | Source registered in the current Clarinet workspace | +|---|---|---|---| +| `core` | `genesis-core-v10` | Profile progression, mission routing, and badge claim entrypoint used by the reference application | No | +| `missions` | `genesis-missions-v10` | Mission completion state reads | No | +| `badges` | `genesis-badges-v10` | Badge module identifier reserved by the runtime registry | No | +| `leaderboard` | `genesis-leaderboard-v1` | Score and rank-tier reads | No | +| `boost` | `genesis-boost-v1` | Progression boost module | No | +| `chainTap` | `chaintap` | Tap-style engagement module | Yes | +| `tokenPoin` | `token-poin` | POIN fungible-token balance reads | No | +| `tokenOne` | `token-one` | ONE fungible-token balance reads | Yes | + +The SDK imports these values from `sdk/contracts.js`. Application code should import the registry instead of duplicating addresses or contract names. + +## Local Clarinet workspace + +`smart-contracts/Clarinet.toml` currently registers: + +| Local contract | Intended status in this repository | Configured by the runtime registry | +|---|---|---| +| `chaintap` | Included source with local tests and a configured mainnet counterpart | Yes | +| `token-one` | Included source with local tests and a configured mainnet counterpart | Yes | +| `reputation-engine` | Local contract source available for development or evaluation | No | + +`reputation-engine` must not be assumed to be a production dependency until it is deployed, reviewed, added to the canonical registry, documented, and covered by integration tests. + +## Compatibility boundaries + +### Application and SDK + +The application and SDK must resolve contract identifiers through the registry. A registry change is a runtime compatibility change and requires: + +1. a confirmed deployment; +2. a review of public function and map compatibility; +3. SDK and frontend tests; +4. documentation updates; +5. an explicit SDK version decision. + +### Contract sources + +Adding a contract source to the Clarinet workspace does not automatically update the production application. Removing a source from the workspace does not remove a deployed contract from the chain. + +### Immutable deployments + +Deployed Clarity logic is not edited in place. Behavioral changes require a new contract version, for example `genesis-core-v11`, followed by a controlled registry and migration update. + +## Mission reward trust boundary + +The current v10 mission interface accepts a reward argument from the caller for compatibility. The reference application derives that value from `MISSION_CATALOG`, but frontend-supplied arguments are not a security boundary. Contract authorization and contract-controlled reward state should be treated as the target design for the next mission-contract version. + +Until that migration is complete: + +- never accept an arbitrary reward value from user input; +- derive the value from the canonical mission registry; +- keep contract-side authorization active; +- test duplicate completion and unauthorized-call paths; +- monitor confirmed state rather than trusting a wallet callback. + +## Adding a new production contract + +1. Add the source and Simnet tests when the source belongs in this repository. +2. Document admin roles, public functions, maps, tokens, and post-condition expectations. +3. Test locally and on testnet. +4. Complete security review and operational approval. +5. Deploy and record the confirmed contract identifier. +6. Add the identifier to `sdk/contracts.js`. +7. Update SDK behavior tests and frontend integration. +8. Update this inventory and the deployment notes. +9. Release the SDK and frontend deliberately. + +See [Deployment Guide](DEPLOYMENT.md), [Write Transactions](WRITE_TRANSACTIONS.md), and [Security Policy](SECURITY.md). From c402ccb37fc32764d222766f3ac1dd8645a25810 Mon Sep 17 00:00:00 2001 From: SMOKAHONTAS <69312778+bayyubenjamin@users.noreply.github.com> Date: Thu, 2 Jul 2026 23:11:55 +0700 Subject: [PATCH 03/11] docs: add transaction integration guide --- docs/WRITE_TRANSACTIONS.md | 173 +++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 docs/WRITE_TRANSACTIONS.md diff --git a/docs/WRITE_TRANSACTIONS.md b/docs/WRITE_TRANSACTIONS.md new file mode 100644 index 00000000..7516114b --- /dev/null +++ b/docs/WRITE_TRANSACTIONS.md @@ -0,0 +1,173 @@ +# Write Transactions + +The StacksOne `2.x` SDK is read-oriented. It provides protocol reads, registries, helpers, and browser wallet connection. The reference application performs contract writes with `openContractCall` so the function name, Clarity arguments, post conditions, and confirmation behavior remain visible to the integrating application. + +## Transaction lifecycle + +Treat every write as four separate states: + +```text +idle → wallet opened → submitted → confirmed or failed +``` + +`onFinish` from the wallet means the transaction was submitted. It does not prove that the transaction was mined successfully or that the expected contract state has changed. + +A confirmation-safe UI should: + +1. validate local input; +2. open the wallet request; +3. store the returned transaction identifier; +4. show a pending state; +5. poll or refresh the relevant on-chain read; +6. mark the action complete only when the expected state is readable; +7. expose a recoverable error or retry state when confirmation fails. + +## Use the canonical registry + +Never duplicate production addresses in a component. + +```js +import { STACKSONE_MAINNET } from '@bayybays/stacksone-sdk/contracts'; +import { resolveStacksNetwork } from '@bayybays/stacksone-sdk/network'; + +const network = resolveStacksNetwork('mainnet'); +const { deployer, contracts } = STACKSONE_MAINNET; +``` + +## Example: complete a mission + +```js +import { openContractCall } from '@stacks/connect'; +import { PostConditionMode, uintCV } from '@stacks/transactions'; +import { + MISSION_CATALOG, + STACKSONE_MAINNET, +} from '@bayybays/stacksone-sdk/contracts'; +import { resolveStacksNetwork } from '@bayybays/stacksone-sdk/network'; + +const network = resolveStacksNetwork('mainnet'); + +export async function submitMission(taskId) { + const mission = MISSION_CATALOG.find((item) => item.id === Number(taskId)); + + if (!mission) { + throw new RangeError(`Unknown mission id: ${taskId}`); + } + + return new Promise((resolve, reject) => { + Promise.resolve( + openContractCall({ + network, + contractAddress: STACKSONE_MAINNET.deployer, + contractName: STACKSONE_MAINNET.contracts.core, + functionName: 'complete-mission', + functionArgs: [uintCV(mission.id), uintCV(mission.reward)], + postConditionMode: PostConditionMode.Deny, + onFinish: resolve, + onCancel: () => resolve(null), + }), + ).catch(reject); + }); +} +``` + +The reward is derived from `MISSION_CATALOG`, not arbitrary user input. This reduces accidental drift, but it is not a replacement for contract-side authorization. The current v10 compatibility interface still accepts a caller-supplied reward argument; a future contract version should resolve rewards from contract-controlled state. + +## Confirm the expected state + +After submission, read the chain again: + +```js +import { StacksOneClient } from '@bayybays/stacksone-sdk'; + +const client = new StacksOneClient({ network: 'mainnet' }); + +async function waitForMission(address, taskId, options = {}) { + const intervalMs = options.intervalMs ?? 10_000; + const attempts = options.attempts ?? 18; + + for (let attempt = 0; attempt < attempts; attempt += 1) { + if (await client.isTaskDone(address, taskId)) return true; + await new Promise((resolve) => setTimeout(resolve, intervalMs)); + } + + return false; +} +``` + +Production applications should also inspect the transaction status through a Stacks API or explorer endpoint. The state read remains the strongest application-level confirmation that the expected protocol effect is present. + +## Example: claim a badge + +```js +import { openContractCall } from '@stacks/connect'; +import { PostConditionMode, stringAsciiCV } from '@stacks/transactions'; +import { STACKSONE_MAINNET } from '@bayybays/stacksone-sdk/contracts'; +import { resolveStacksNetwork } from '@bayybays/stacksone-sdk/network'; + +const network = resolveStacksNetwork('mainnet'); + +export function claimBadge(badgeId) { + return new Promise((resolve, reject) => { + Promise.resolve( + openContractCall({ + network, + contractAddress: STACKSONE_MAINNET.deployer, + contractName: STACKSONE_MAINNET.contracts.core, + functionName: 'claim-badge', + functionArgs: [stringAsciiCV(badgeId)], + postConditionMode: PostConditionMode.Deny, + onFinish: resolve, + onCancel: () => resolve(null), + }), + ).catch(reject); + }); +} +``` + +Before opening the wallet, use `checkBadgeEligibility()` for user feedback. The contract must still enforce the real claim rules. + +## Post-condition policy + +Use restrictive post conditions for any transaction that can move assets. `PostConditionMode.Deny` is a safer default because undeclared asset transfers fail rather than pass silently. + +For each write, document: + +- which fungible tokens or NFTs can move; +- the maximum amount; +- the expected sender and recipient; +- whether the operation can mint or burn an asset; +- what the UI should display when a post condition rejects the call. + +Do not copy permissive post-condition settings merely to make a transaction succeed. + +## Error handling + +Handle at least these cases separately: + +| Case | Recommended UI state | +|---|---| +| Wallet unavailable | Explain that a browser wallet is required | +| User cancellation | Return to idle without reporting a protocol failure | +| Invalid local input | Block the wallet request and show the exact field error | +| Submission error | Preserve form state and allow retry | +| Submitted but unconfirmed | Keep the transaction pending and show the transaction identifier | +| Confirmed failure | Show the chain error and do not update local success state | +| Confirmed success but stale cache | Refresh chain state and treat the cache as secondary | + +## Integration checklist + +Before shipping a new write path: + +- import the contract identifier from the registry; +- validate and encode every Clarity argument explicitly; +- define restrictive post conditions; +- distinguish cancellation from failure; +- store the transaction identifier; +- keep the UI pending after submission; +- confirm the expected state through a chain read; +- test duplicate, unauthorized, malformed, and insufficient-balance paths; +- document any admin or trust assumptions; +- update the contract inventory when a new contract is introduced. + +See [Contract Inventory](CONTRACTS.md), [System Architecture](SYSTEM_ARCHITECTURE.md), and [Security Policy](SECURITY.md). From eb93099854eda2b6ef8b51b8bf31caab3c23bbed Mon Sep 17 00:00:00 2001 From: SMOKAHONTAS <69312778+bayyubenjamin@users.noreply.github.com> Date: Thu, 2 Jul 2026 23:12:26 +0700 Subject: [PATCH 04/11] docs: add release and deployment guide --- docs/DEPLOYMENT.md | 203 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 docs/DEPLOYMENT.md diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md new file mode 100644 index 00000000..163a9f27 --- /dev/null +++ b/docs/DEPLOYMENT.md @@ -0,0 +1,203 @@ +# Deployment Guide + +StacksOne has four separate release surfaces: + +1. Clarity contract deployment; +2. canonical registry update; +3. npm SDK release; +4. reference frontend deployment. + +Treat them as separate approvals. A successful contract deployment does not automatically update the SDK or frontend, and publishing an SDK must not point users to an unconfirmed contract. + +## Preflight checks + +From the repository root: + +```bash +npm ci +npm test +npm run build +npm pack --dry-run +``` + +From the contract workspace: + +```bash +cd smart-contracts +npm ci +npm test +``` + +Before any public release, also confirm: + +- the working tree contains only the intended changes; +- contract public functions and maps match the integration assumptions; +- admin principals and deployment accounts are documented; +- no private keys, seed phrases, or production secrets are committed; +- the target network is explicit; +- asset-moving calls have reviewed post conditions; +- migration and rollback behavior is documented. + +## 1. Contract release + +### Local validation + +Use the Clarinet workspace for the contract sources registered in `smart-contracts/Clarinet.toml`. Add or update Simnet tests for: + +- successful public calls; +- unauthorized callers; +- duplicate operations; +- boundary values; +- asset balances and ownership; +- map and variable state; +- expected error codes. + +The repository does not expose a single root `npm run deploy` command. Contract deployment must therefore use an explicitly reviewed Clarinet plan, Stacks CLI flow, or maintained deployment script. Do not document an ad-hoc private-key command as the canonical release process. + +### Testnet before mainnet + +For a behavior-changing contract: + +1. deploy a versioned testnet contract; +2. exercise the real wallet flow; +3. verify API reads and transaction confirmation behavior; +4. verify admin operations with the intended signer model; +5. run frontend integration against the testnet identifier; +6. record the final public interface and known limitations. + +### Mainnet deployment record + +For every mainnet deployment, record: + +```text +network: +deployer: +contract name: +source commit: +deployment transaction id: +confirmed block: +admin or multisig policy: +public interface compatibility: +migration notes: +``` + +Do not update the runtime registry until the deployment is confirmed and independently checked. + +## 2. Registry release + +The canonical runtime configuration lives in `sdk/contracts.js`. + +A registry update must: + +- use the exact confirmed deployer and contract name; +- preserve old identifiers when compatibility requires them; +- include tests for `getContractId()` and affected client methods; +- update `docs/CONTRACTS.md`; +- update transaction examples when public functions or arguments changed; +- state whether the change is patch, minor, or major for the SDK. + +A contract-name change can alter production behavior without changing application code. Review registry changes with the same care as code changes. + +## 3. SDK release + +The npm package is `@bayybays/stacksone-sdk`. + +### Validate package contents + +```bash +npm test +npm run build +npm pack --dry-run +``` + +Confirm that the package contains only the intended public files: + +```text +index.js +sdk/ +README.md +LICENSE +``` + +### Version decision + +Use semantic versioning deliberately: + +- **patch**: documentation, internal fixes, or behavior corrections that preserve the public API; +- **minor**: backward-compatible methods, registries, helpers, or supported capabilities; +- **major**: removed exports, changed return shapes, incompatible defaults, or contract integrations that break existing consumers. + +Before publishing: + +1. update the package version; +2. update public documentation and examples; +3. run the package tests against the packed artifact when practical; +4. verify the npm account and package scope; +5. publish from a clean, reviewed commit; +6. verify the published version and subpath exports. + +## 4. Frontend release + +The reference frontend must be built against the same registry and SDK behavior that passed review. + +```bash +npm ci +npm test +npm run build +``` + +Production environment rules: + +- Supabase variables are optional and must not contain privileged service-role credentials in the browser; +- the frontend must not contain deployer private keys; +- chain state remains authoritative; +- submitted writes remain pending until confirmed state is readable; +- stale cache data must not overwrite confirmed chain data; +- contract identifiers must come from the canonical registry. + +After deployment, smoke-test: + +- application startup; +- wallet connection and cancellation; +- profile and leaderboard reads; +- token balances; +- mission status; +- badge status; +- at least one low-risk write path when operationally appropriate; +- pending, confirmed, rejected, and failed transaction states. + +## Rollback and recovery + +### Frontend + +Redeploy the last known-good frontend artifact or commit. Do not mask an incompatible registry change with cached data. + +### SDK + +Deprecate a broken npm release and publish a corrected version. Avoid deleting published versions that consumers may already depend on. + +### Registry + +Restore the last known-good identifiers only when the old contracts remain compatible and safe. Document why the new deployment was rejected. + +### Contracts + +Deployed Clarity logic is immutable. A contract bug requires a new version, migration strategy, registry update, and operational communication. A frontend rollback cannot repair unsafe contract behavior. + +## Release checklist + +- [ ] Root tests pass. +- [ ] Frontend production build passes. +- [ ] `npm pack --dry-run` is reviewed. +- [ ] Contract tests pass. +- [ ] Security boundaries and admin roles are reviewed. +- [ ] Testnet integration is complete for behavior-changing contracts. +- [ ] Mainnet deployment is confirmed. +- [ ] `sdk/contracts.js` matches the confirmed deployment. +- [ ] Contract inventory is current. +- [ ] Transaction examples match the public interface. +- [ ] SDK version impact is classified. +- [ ] Frontend environment contains no privileged secrets. +- [ ] Migration and recovery notes are available. + +See [Contract Inventory](CONTRACTS.md), [Development Workflow](WORKFLOW.md), and [Security Policy](SECURITY.md). From e147e052b5bc2767fcc4ba715beeafbe549bccd4 Mon Sep 17 00:00:00 2001 From: SMOKAHONTAS <69312778+bayyubenjamin@users.noreply.github.com> Date: Thu, 2 Jul 2026 23:13:04 +0700 Subject: [PATCH 05/11] docs: expand SDK API reference --- docs/SDK_API.md | 364 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 336 insertions(+), 28 deletions(-) diff --git a/docs/SDK_API.md b/docs/SDK_API.md index d9bbc2fd..f411a73b 100644 --- a/docs/SDK_API.md +++ b/docs/SDK_API.md @@ -1,42 +1,350 @@ # SDK API Reference +Package: + +```bash +npm install @bayybays/stacksone-sdk +``` + +The `2.x` SDK is an ES module package for normalized protocol reads, contract registries, progression helpers, and browser wallet connection. Contract writes remain explicit application integrations; see [Write Transactions](WRITE_TRANSACTIONS.md). + +## `StacksOneClient` + +```js +import { StacksOneClient } from '@bayybays/stacksone-sdk'; + +const client = new StacksOneClient({ + network: 'mainnet', +}); +``` + +### Constructor options + +```ts +new StacksOneClient({ + network?, + deployer?, + contracts?, + appDetails?, + readOnly?, + fetcher?, + decode?, + decodeHex?, + userSession?, +}) +``` + +| Option | Purpose | Default | +|---|---|---| +| `network` | `'mainnet'`, `'testnet'`, or a compatible Stacks network object | `'mainnet'` | +| `deployer` | Contract deployer used by reads | `STACKSONE_MAINNET.deployer` | +| `contracts` | Partial override of canonical contract names | `STACKSONE_MAINNET.contracts` | +| `appDetails` | Wallet application `name` and `icon` | StacksOne defaults | +| `readOnly` | Injectable read-only function for tests or custom transports | `callReadOnlyFunction` | +| `fetcher` | Injectable `fetch` implementation for map reads | `globalThis.fetch` | +| `decode` | Decoder for read-only Clarity responses | `cvToValue` | +| `decodeHex` | Decoder for map-entry hex values | `hexToCV` followed by `cvToValue` | +| `userSession` | Existing browser `UserSession` | Created lazily by `connectWallet()` | + +Changing `network` to `'testnet'` does not automatically replace the default mainnet deployer or contract names. Provide explicit `deployer` and `contracts` overrides when integrating a testnet deployment. + ## Client methods -| Method | Purpose | +### `getUserProfile(address)` + +Reads the `user-profile` map from the configured core contract. + +```ts +getUserProfile(address: string): Promise<{ + xp: number; + level: number; +}> +``` + +Example: + +```js +const profile = await client.getUserProfile(address); +// { xp: 1250, level: 3 } +``` + +A missing map entry is normalized to: + +```js +{ xp: 0, level: 1 } +``` + +### `getUserStats(address)` + +Combines profile, leaderboard score, and rank tier reads. + +```ts +getUserStats(address: string): Promise<{ + address: string; + xp: number; + level: number; + score: number; + rankTier: number; +}> +``` + +Example: + +```js +const stats = await client.getUserStats(address); + +// { +// address, +// xp: 1250, +// level: 3, +// score: 725, +// rankTier: 2, +// } +``` + +### `getLeaderboardScore(address)` + +Calls `get-score` on the configured leaderboard contract and returns a normalized safe number. + +```ts +getLeaderboardScore(address: string): Promise +``` + +Invalid or unsupported decoded numeric values fall back to `0`. + +### `getRankTier(address)` + +Calls `get-rank-tier` on the configured leaderboard contract. + +```ts +getRankTier(address: string): Promise +``` + +The local helper uses these thresholds: + +| Score | Tier | |---|---| -| `getUserProfile(address)` | Read XP and level | -| `getUserStats(address)` | Combine profile, score, and rank tier | -| `getLeaderboardScore(address)` | Read leaderboard score | -| `getRankTier(address)` | Read rank tier | -| `getTokenBalance(address, token)` | Read `one` or `poin` base units | -| `isTaskDone(address, taskId)` | Read mission completion | -| `hasBadge(address, badgeId)` | Read badge ownership | -| `checkBadgeEligibility(input)` | Evaluate ownership and profile thresholds | -| `connectWallet()` | Open browser wallet connection | -| `callReadOnly(...)` | Call a configured read-only function | -| `readMapEntry(...)` | Read and decode a contract map entry | +| `0–99` | `0` | +| `100–499` | `1` | +| `500–999` | `2` | +| `1000+` | `3` | + +The contract remains authoritative for the value returned by `client.getRankTier()`. + +### `getTokenBalance(address, token)` + +Reads a SIP-010-style balance from the configured token contract. + +```ts +getTokenBalance( + address: string, + token: 'one' | 'poin', +): Promise +``` + +Balances are returned in contract base units. The SDK does not apply display decimals. + +```js +const oneBaseUnits = await client.getTokenBalance(address, 'one'); +``` + +An unsupported token name throws `TypeError`. + +### `isTaskDone(address, taskId)` + +Calls `is-task-done` on the configured mission contract. + +```ts +isTaskDone(address: string, taskId: number): Promise +``` + +`taskId` must be a non-negative safe integer. + +### `hasBadge(address, badgeId)` + +Reads the `wallet-has-badge` map from the configured core contract. + +```ts +hasBadge(address: string, badgeId: string): Promise +``` + +This is a low-level ownership read and accepts any non-empty badge identifier. Use `checkBadgeEligibility()` when you want catalog validation and progression requirements. + +### `checkBadgeEligibility(input)` + +Combines badge catalog metadata, profile state, and current ownership. + +```ts +checkBadgeEligibility({ + user: string, + badgeId: 'genesis' | 'node' | 'guardian', +}): Promise<{ + user: string; + badgeId: string; + owned: boolean; + eligible: boolean; + profile: { xp: number; level: number }; + requirements: { + minXP: number; + minLevel: number; + xpMet: boolean; + levelMet: boolean; + }; +}> +``` + +Eligibility is frontend guidance. The contract must enforce the real claim rules. + +Unknown catalog identifiers throw `RangeError`. + +### `connectWallet()` + +Opens the browser Stacks wallet connection flow. + +```ts +connectWallet(): Promise +``` + +- resolves with `userSession.loadUserData()` after a successful connection; +- resolves with `null` when the user cancels; +- rejects when called outside a browser environment. + +This method connects a wallet. It does not submit a contract call. + +### `callReadOnly(...)` + +Advanced wrapper around the configured read-only transport. + +```ts +callReadOnly( + contractName: string, + functionName: string, + functionArgs: ClarityValue[], + senderAddress: string, +): Promise +``` + +The result is the raw response returned by the configured `readOnly` implementation. Use this method when a public read is not yet represented by a higher-level client method. + +### `readMapEntry(...)` + +Advanced Stacks API map-entry reader. + +```ts +readMapEntry( + contractName: string, + mapName: string, + key: ClarityValue, +): Promise +``` + +A `404` response is treated as a missing record and returns `null`. Other non-success responses throw `Error` with the HTTP status. ## Registries -`STACKSONE_MAINNET` contains the canonical deployer and contract names. `MISSION_CATALOG` and `BADGE_CATALOG` contain metadata shared by the SDK and frontend. +Import focused registry exports from the package subpath: + +```js +import { + BADGE_CATALOG, + MISSION_CATALOG, + STACKSONE_MAINNET, + getContractId, + getMission, + getTaskReward, +} from '@bayybays/stacksone-sdk/contracts'; +``` + +### `STACKSONE_MAINNET` + +Contains: + +```ts +{ + network: 'mainnet'; + deployer: string; + contracts: { + core: string; + missions: string; + badges: string; + leaderboard: string; + boost: string; + chainTap: string; + tokenPoin: string; + tokenOne: string; + }; +} +``` + +See [Contract Inventory](CONTRACTS.md) before changing the registry. + +### `MISSION_CATALOG` -Configured badge identifiers are `genesis`, `node`, and `guardian`. +Contains canonical frontend metadata for mission IDs `101–110`, including name, description, reward, and icon. -## Helpers +### `BADGE_CATALOG` + +Configured badge identifiers are: + +- `genesis`; +- `node`; +- `guardian`. + +## Helper exports + +```js +import { + assertStacksAddress, + calculateLevel, + getExplorerContractUrl, + getRankTier, + normalizeProfile, + toBoolean, + toSafeNumber, +} from '@bayybays/stacksone-sdk'; +``` + +| Helper | Behavior | +|---|---| +| `calculateLevel(xp)` | Returns `Math.floor(xp / 500) + 1` | +| `getRankTier(score)` | Returns local tier `0–3` using the documented thresholds | +| `getMission(taskId)` | Returns matching mission metadata or `null` | +| `getTaskReward(taskId)` | Returns the configured reward or `null` | +| `getContractId(name, deployer?)` | Returns `deployer.contract-name` | +| `getExplorerContractUrl(name, deployer?)` | Returns the mainnet Hiro explorer contract URL | +| `resolveStacksNetwork(value)` | Resolves mainnet, testnet, or passes through a network object | +| `assertStacksAddress(address)` | Validates a Stacks standard principal string | +| `normalizeProfile(value)` | Returns normalized `{ xp, level }` with level at least `1` | +| `toSafeNumber(value, fallback?)` | Unwraps common decoded shapes into a safe number | +| `toBoolean(value, fallback?)` | Unwraps common decoded shapes into a boolean | + +## Error behavior + +| Condition | Error or result | +|---|---| +| Invalid Stacks address | `TypeError` | +| Invalid token name | `TypeError` | +| Negative or unsafe task ID | `TypeError` | +| Empty contract or function name | `TypeError` | +| Unknown catalog badge in `checkBadgeEligibility()` | `RangeError` | +| No fetch implementation for map reads | `Error` | +| Map-entry API returns `404` | `null` | +| Other map-entry API failure | `Error` containing HTTP status | +| Wallet connection outside browser | Rejected `Error` | +| Wallet cancellation | `null` | -- `calculateLevel(xp)` -- `getRankTier(score)` -- `getMission(taskId)` -- `getTaskReward(taskId)` -- `getContractId(name, deployer?)` -- `getExplorerContractUrl(name, deployer?)` -- `resolveStacksNetwork(value)` -- `assertStacksAddress(address)` -- `toSafeNumber(value, fallback?)` -- `toBoolean(value, fallback?)` +## Deterministic test injection -Invalid addresses and token names throw `TypeError`. Unknown badge identifiers throw `RangeError`. Missing map entries return `null`. +`StacksOneClient` accepts custom network, transport, fetcher, and decoding functions. This allows tests without live network calls: -## Test injection +```js +const client = new StacksOneClient({ + network: { coreApiUrl: 'https://api.example.test' }, + readOnly: async (request) => mockRead(request), + fetcher: async (url, options) => mockFetch(url, options), + decode: (value) => value, + decodeHex: (value) => mockDecodedMap[value] ?? null, +}); +``` -`StacksOneClient` accepts custom `network`, `readOnly`, `fetcher`, `decode`, and `decodeHex` options. This allows deterministic tests without live network calls. See `tests/client.test.js`. +Keep public behavior tests in `tests/` whenever a method, normalized return shape, error class, registry key, or helper threshold changes. From e4c25259fd94858271d2e256931c82b1d1ae8466 Mon Sep 17 00:00:00 2001 From: SMOKAHONTAS <69312778+bayyubenjamin@users.noreply.github.com> Date: Thu, 2 Jul 2026 23:13:21 +0700 Subject: [PATCH 06/11] docs: strengthen SDK quick start --- docs/SDK_QUICKSTART.md | 81 +++++++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 12 deletions(-) diff --git a/docs/SDK_QUICKSTART.md b/docs/SDK_QUICKSTART.md index 4d582c99..f37a01e7 100644 --- a/docs/SDK_QUICKSTART.md +++ b/docs/SDK_QUICKSTART.md @@ -1,12 +1,21 @@ # SDK Quick Start -Install the ES module package: +The StacksOne `2.x` SDK is an ES module package for normalized on-chain reads, canonical registries, progression helpers, and browser wallet connection. + +## Requirements + +- Node.js `>=18.18`; +- an ESM-compatible build environment; +- `fetch` support for map-entry reads; +- a browser environment only when calling `connectWallet()`. + +## Install ```bash npm install @bayybays/stacksone-sdk ``` -Create a mainnet client: +## Create a mainnet client ```js import { StacksOneClient } from '@bayybays/stacksone-sdk'; @@ -20,44 +29,92 @@ const client = new StacksOneClient({ }); ``` -Read a complete profile and leaderboard summary: +## Read a complete user summary ```js const stats = await client.getUserStats(address); + +// { +// address, +// xp, +// level, +// score, +// rankTier, +// } ``` -Read configured token balances in base units: +## Read token balances ```js -const one = await client.getTokenBalance(address, 'one'); -const poin = await client.getTokenBalance(address, 'poin'); +const oneBaseUnits = await client.getTokenBalance(address, 'one'); +const poinBaseUnits = await client.getTokenBalance(address, 'poin'); ``` -Read mission and badge state: +Balances are returned in contract base units. Apply token display decimals in your application when needed. + +## Read mission and badge state ```js const completed = await client.isTaskDone(address, 101); const owned = await client.hasBadge(address, 'node'); + const eligibility = await client.checkBadgeEligibility({ user: address, badgeId: 'node', }); ``` -Connect a browser wallet: +Eligibility is user-interface guidance. Contract authorization remains authoritative. + +## Connect a browser wallet ```js const userData = await client.connectWallet(); + +if (!userData) { + // The user cancelled the wallet flow. +} ``` -Package subpaths are available for focused imports: +`connectWallet()` rejects outside a browser environment. It connects a wallet but does not submit a contract transaction. + +## Focused imports ```js -import { STACKSONE_MAINNET } from '@bayybays/stacksone-sdk/contracts'; +import { + MISSION_CATALOG, + STACKSONE_MAINNET, +} from '@bayybays/stacksone-sdk/contracts'; import { resolveStacksNetwork } from '@bayybays/stacksone-sdk/network'; import { calculateLevel } from '@bayybays/stacksone-sdk/utils'; ``` -A wallet callback means the transaction was submitted, not confirmed. Mark writes as pending and read the chain again before presenting final state. +## Testnet or custom deployment + +The network selection and contract registry are independent. Selecting testnet does not replace the default mainnet deployer automatically. + +```js +const testnetClient = new StacksOneClient({ + network: 'testnet', + deployer: 'ST...', + contracts: { + core: 'genesis-core-v11-testnet', + missions: 'genesis-missions-v11-testnet', + leaderboard: 'genesis-leaderboard-v2-testnet', + }, +}); +``` + +Provide only the contract keys you need to override; the remaining keys inherit the canonical defaults. For production testnet integration, override every contract that could otherwise resolve to a mainnet deployment name. + +## Transaction writes + +The current SDK intentionally leaves write construction to the integrating application. Use the canonical registry with `openContractCall`, encode arguments explicitly, define post conditions, and keep the UI pending until confirmed state is readable. + +A wallet `onFinish` callback means the transaction was submitted, not confirmed. + +Read: -See [SDK API Reference](SDK_API.md) for the complete public surface. +- [SDK API Reference](SDK_API.md); +- [Write Transactions](WRITE_TRANSACTIONS.md); +- [Contract Inventory](CONTRACTS.md). From f224c4570097a86e43ed3e5ce860a0ceec3f861a Mon Sep 17 00:00:00 2001 From: SMOKAHONTAS <69312778+bayyubenjamin@users.noreply.github.com> Date: Thu, 2 Jul 2026 23:13:46 +0700 Subject: [PATCH 07/11] docs: clarify system architecture --- docs/SYSTEM_ARCHITECTURE.md | 183 ++++++++++++++++++++++++++++++++++-- 1 file changed, 173 insertions(+), 10 deletions(-) diff --git a/docs/SYSTEM_ARCHITECTURE.md b/docs/SYSTEM_ARCHITECTURE.md index 82762fc0..917a9cda 100644 --- a/docs/SYSTEM_ARCHITECTURE.md +++ b/docs/SYSTEM_ARCHITECTURE.md @@ -1,19 +1,182 @@ # System Architecture +StacksOne separates presentation, integration, chain access, and authoritative protocol state. + ```text -React application - ↓ -StacksOne SDK and registry - ↓ -Stacks API reads + wallet submissions - ↓ -Clarity contracts +React reference application + ↓ +StacksOne SDK + canonical contract registry + ↓ +Stacks API reads + browser wallet submissions + ↓ +Configured Clarity contracts ``` Supabase is optional. Confirmed on-chain records remain authoritative. -The protocol is separated into core progression, missions, badges, tokens, leaderboard, reputation, boost, and engagement modules. +## Layer responsibilities + +### React reference application + +The frontend owns: + +- navigation and presentation; +- wallet interaction prompts; +- local input validation; +- pending, confirmed, cancelled, and failed transaction states; +- display formatting for base-unit balances; +- optional cache synchronization. + +The frontend does not own authorization, balances, badge ownership, mission completion, or final transaction truth. + +### StacksOne SDK + +The SDK owns: + +- normalized read methods; +- the canonical runtime contract registry; +- network resolution; +- mission and badge metadata shared with the frontend; +- progression and decoding helpers; +- browser wallet connection; +- deterministic injection points for tests. + +The `2.x` SDK is intentionally read-oriented. The reference application constructs writes explicitly with `openContractCall`. + +### Stacks APIs and wallet providers + +Stacks APIs provide read access to contract functions and maps. Browser wallets provide user-approved transaction submission. + +Neither layer alone proves the final application state: + +- a wallet callback proves submission, not confirmation; +- an API cache can be stale; +- the application should read the expected contract state after the transaction confirms. + +### Clarity contracts + +Configured Clarity contracts own the authoritative protocol rules and state, including: + +- progression profile data; +- mission completion; +- badge ownership and claim authorization; +- token balances; +- leaderboard score and rank; +- engagement and boost behavior. + +Frontend checks are convenience controls. Contract checks are security controls. + +## Data authority + +Use this precedence order: + +```text +confirmed contract state + ↓ +Stacks API representation of confirmed state + ↓ +optional Supabase index or cache + ↓ +local React state +``` + +Lower layers may improve responsiveness but must not overwrite or contradict a confirmed higher-authority result. + +## Transaction lifecycle + +```text +1. Local validation +2. Wallet request opened +3. User approves or cancels +4. Transaction submitted +5. UI stores transaction identifier and remains pending +6. Transaction confirms or fails +7. Application reads expected contract state +8. UI presents final result +``` + +A component must not grant XP, mark a task complete, or show badge ownership merely because `onFinish` fired. + +See [Write Transactions](WRITE_TRANSACTIONS.md). + +## Contract registry versus Clarinet workspace + +The repository has two different contract surfaces: + +```text +sdk/contracts.js + = contracts used by the SDK and reference application + +smart-contracts/Clarinet.toml + = contract sources included in the current local test workspace +``` + +These files are not expected to contain identical inventories. A historical mainnet contract may be configured without its source being registered locally. A local experimental contract may exist without being a runtime dependency. + +See [Contract Inventory](CONTRACTS.md). + +## Module boundaries + +The runtime registry currently separates: + +- core progression; +- missions; +- badges; +- leaderboard; +- boost; +- ChainTap engagement; +- POIN token; +- ONE token. + +The local Clarinet workspace additionally contains `reputation-engine`, which is not currently part of the runtime registry. + +Modules should communicate through documented public functions rather than duplicated assumptions in frontend code. + +## Configuration boundaries + +### Network + +`resolveStacksNetwork()` selects a mainnet, testnet, or custom network object. + +### Contract deployment + +Network selection does not automatically select a matching deployer or contract set. A testnet integration must provide explicit testnet identifiers. + +### Optional Supabase configuration + +Only browser-safe anonymous configuration belongs in Vite environment variables. Service-role keys, deployer private keys, and seed phrases must never be exposed in frontend code. + +## Failure model + +The architecture assumes these failures are normal and recoverable: + +- wallet unavailable; +- user cancellation; +- API timeout or stale response; +- transaction remains pending; +- confirmed contract error; +- missing map entry; +- optional cache unavailable; +- contract version mismatch. + +Components should preserve enough information for a retry and should never convert an uncertain state into a success state. + +## Change impact + +| Change | Required review | +|---|---| +| UI-only presentation | Frontend build and affected interaction checks | +| SDK normalized return shape | Public tests, API docs, semantic-version review | +| Registry identifier | Deployment verification, integration tests, contract inventory | +| Contract public interface | Simnet tests, write integration, migration and version plan | +| Authorization or asset movement | Security review, post conditions, admin model | +| Supabase schema or cache behavior | Proof that chain state remains authoritative | -The deployer and application contract names are centralized in `sdk/contracts.js`. UI components import the registry rather than repeating identifiers. +## Design invariants -Wallet request, transaction submission, and confirmed chain state are separate stages. Writes remain pending until a later read exposes the expected result. +- Contract state is authoritative. +- Registry identifiers are centralized. +- Writes remain pending until confirmed state is readable. +- Optional infrastructure may fail without corrupting protocol truth. +- Contract upgrades are versioned rather than edited in place. +- Public SDK behavior is testable without live network calls. From 5cc094750da551eba98366769092c88359228f4d Mon Sep 17 00:00:00 2001 From: SMOKAHONTAS <69312778+bayyubenjamin@users.noreply.github.com> Date: Thu, 2 Jul 2026 23:14:15 +0700 Subject: [PATCH 08/11] docs: define development workflow --- docs/WORKFLOW.md | 171 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 151 insertions(+), 20 deletions(-) diff --git a/docs/WORKFLOW.md b/docs/WORKFLOW.md index 8c00d525..554a90fd 100644 --- a/docs/WORKFLOW.md +++ b/docs/WORKFLOW.md @@ -1,43 +1,174 @@ # Development Workflow -## Root project +Use this workflow to keep contract behavior, the SDK, the reference frontend, and the documentation aligned. + +## Requirements + +- Node.js `>=18.18`; +- npm; +- Clarinet tooling when changing or deploying Clarity contracts; +- a browser Stacks wallet for manual write-flow validation. + +## Initial setup ```bash +git clone https://github.com/bayyubenjamin/stacksone.git +cd stacksone npm ci -npm run dev +cp .env.example .env +``` + +Supabase configuration is optional. Leave both environment values empty when working only with wallet and on-chain features. + +Install the contract-test dependencies separately: + +```bash +cd smart-contracts +npm ci +``` + +## Root project checks + +Run from the repository root: + +```bash npm test npm run build npm pack --dry-run ``` -The root tests cover the public SDK. The build validates the React application, and the package dry-run verifies the files prepared for npm publication. +| Command | Validates | +|---|---| +| `npm test` | Public SDK methods, normalization, registries, and helper behavior | +| `npm run build` | React application production compilation | +| `npm pack --dry-run` | Files and metadata prepared for npm publication | +| `npm run lint` | Repository lint rules when lint validation is needed | + +## Smart-contract checks -## Smart contracts +Run from `smart-contracts/`: ```bash -cd smart-contracts -npm ci npm test ``` -Contract tests use the Clarinet SDK, Vitest, and Simnet. +Contract tests use the Clarinet SDK, Vitest, and Simnet. Tests should cover success paths, authorization failures, duplicate operations, boundary values, and expected state changes. ## Recommended change order -1. update contract behavior and Simnet tests; -2. update shared SDK registries or helpers; -3. add SDK behavior tests; -4. update the reference frontend; -5. run root and contract checks; -6. review CI and package contents; -7. release through an explicit deployment or package version. +For a change that crosses layers: + +1. define the intended contract behavior and compatibility impact; +2. update contract source and Simnet tests when applicable; +3. deploy or select the target testnet contract when integration behavior changed; +4. update `sdk/contracts.js` or SDK methods; +5. add public SDK behavior tests; +6. update the reference frontend; +7. update contract, API, transaction, and migration documentation; +8. run root and contract checks; +9. inspect the npm package contents; +10. release contracts, registry, SDK, and frontend as separate approvals. + +Do not begin with a frontend workaround for a contract authorization problem. + +## Change matrix + +| Changed area | Minimum required work | +|---|---| +| React presentation only | Build, interaction smoke test, screenshots when useful | +| SDK helper or normalized return | Root tests, API reference, semantic-version review | +| Contract registry | Confirmed deployment evidence, affected SDK tests, contract inventory | +| Browser write path | Argument validation, post conditions, cancellation and confirmation handling | +| Clarity behavior | Simnet tests, security review, version and migration decision | +| Supabase support | Failure-path test and proof that chain state remains authoritative | +| Public documentation | Verify commands, paths, imports, contract names, and links against the repository | ## Repository rules -- Import contract names from `sdk/contracts.js`. -- Avoid duplicated deployer addresses in UI code. -- Keep submitted writes pending until chain reads confirm state. -- Keep optional cache data secondary to on-chain records. -- Document migrations and compatibility changes. +- Import contract names and deployer data from `sdk/contracts.js`. +- Do not duplicate production identifiers in UI components. +- Keep network selection separate from contract deployment selection. +- Keep submitted writes pending until chain reads confirm the expected state. +- Distinguish wallet cancellation, submission failure, confirmed failure, and stale reads. +- Keep optional cache data secondary to confirmed on-chain records. +- Never commit private keys, seed phrases, service-role keys, or production secrets. +- Document admin roles, post conditions, migrations, and compatibility changes. +- Add tests before changing a public return shape or error class. +- Use versioned contract names for behavior changes. + +## SDK development + +The package entrypoint is `index.js`. Public exports are part of the compatibility surface. + +When changing the SDK: + +1. update implementation under `sdk/`; +2. add or update tests under `tests/`; +3. update `docs/SDK_API.md` and examples; +4. verify subpath exports; +5. run `npm pack --dry-run`; +6. classify the semantic-version impact. + +The SDK supports deterministic injection of network, read-only transport, fetch, and decoders. Prefer injected tests over live-network tests for public behavior. + +## Contract development + +The local Clarinet manifest does not represent every configured mainnet contract. Before editing or adding a contract, read [Contract Inventory](CONTRACTS.md). + +For each contract change, document: + +- public functions and argument types; +- maps, variables, tokens, and NFTs affected; +- authorized callers; +- error codes; +- asset movement and post-condition expectations; +- upgrade or migration impact; +- whether the contract is local-only, testnet, or configured mainnet. + +## Write integration + +Before merging a write path: + +- validate the input before opening the wallet; +- derive canonical mission and badge metadata from the registry; +- encode Clarity values explicitly; +- use restrictive post conditions; +- store the transaction identifier; +- leave the UI pending after submission; +- verify the expected contract state; +- test user cancellation and confirmed failure. + +See [Write Transactions](WRITE_TRANSACTIONS.md). + +## Pull-request expectations + +A focused pull request should explain: + +- what changed; +- why the change is required; +- which layer owns the behavior; +- user and developer impact; +- compatibility or migration impact; +- security assumptions; +- checks performed; +- deployment or release work that remains. + +Avoid mixing unrelated design changes, formatting changes, and deployment updates in one review unless they are inseparable. + +## CI behavior + +The repository CI validates: + +- locked root dependency installation; +- public SDK tests; +- frontend production build; +- npm package contents; +- locked contract-test dependency installation; +- contract tests; +- uploaded contract-test diagnostics when the contract job runs. + +A passing CI run is necessary but does not replace testnet validation, mainnet deployment verification, security review, or manual wallet-flow checks. + +## Release workflow -Copy `.env.example` to `.env` only when optional Supabase configuration is needed. +Follow [Deployment Guide](DEPLOYMENT.md). Contracts, the registry, the SDK, and the frontend are separate release surfaces and must not be treated as one automatic deployment. From d13fe05b71cac1218d65e34db54ef51b8a8a5deb Mon Sep 17 00:00:00 2001 From: SMOKAHONTAS <69312778+bayyubenjamin@users.noreply.github.com> Date: Thu, 2 Jul 2026 23:14:46 +0700 Subject: [PATCH 09/11] docs: strengthen security policy --- docs/SECURITY.md | 157 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 143 insertions(+), 14 deletions(-) diff --git a/docs/SECURITY.md b/docs/SECURITY.md index 4768f18a..4c503d1c 100644 --- a/docs/SECURITY.md +++ b/docs/SECURITY.md @@ -2,27 +2,156 @@ ## Supported line -The actively maintained package line is `2.x`. +The actively maintained SDK package line is `2.x`. Deployed contracts are versioned independently; support for a contract version depends on the identifiers currently documented in `sdk/contracts.js` and `docs/CONTRACTS.md`. -## Reporting +## Reporting a vulnerability -Report suspected security issues privately to the repository maintainer. Include the affected component, reproducible steps, observed behavior, expected behavior, and impact. Do not disclose an unresolved issue in a public discussion. +Do not publish an unresolved vulnerability, private key, exploit transaction, or reproducible attack path in a public issue. -## Boundaries +Preferred reporting flow: -- Clarity contracts enforce authorization and ownership. -- Frontend validation is a user-experience control. -- Wallet submission is not final confirmation. -- On-chain records remain authoritative. -- Supabase is optional and must not override chain state. -- Contract identifiers are centralized in `sdk/contracts.js`. +1. use GitHub private vulnerability reporting from the repository Security tab when that option is available; +2. otherwise contact the repository maintainer through the linked GitHub profile before sending sensitive reproduction details; +3. include the affected component, network, contract identifier or package version, reproducible steps, observed behavior, expected behavior, and potential impact; +4. remove seed phrases, private keys, access tokens, personal data, and unrelated wallet information from the report. + +A useful report should state whether the issue affects: + +- a deployed Clarity contract; +- the canonical contract registry; +- the SDK package; +- the reference frontend; +- wallet transaction construction; +- optional Supabase behavior; +- build, CI, or release infrastructure. + +## Security model + +### Authoritative state + +Confirmed Clarity contract state is authoritative. Frontend state and Supabase data are convenience layers and must not override chain truth. + +### Authorization + +Clarity contracts must enforce ownership, admin roles, minting rights, mission completion, badge claims, and asset movement. Frontend eligibility checks are user-experience controls, not authorization controls. + +### Transaction finality + +A wallet callback means a transaction was submitted. The application must keep the operation pending until the transaction status and expected on-chain state are confirmed. + +### Contract identifiers + +Production identifiers are centralized in `sdk/contracts.js`. Duplicating contract addresses in UI code creates configuration drift and can route users to an unintended contract. + +### Network selection + +Choosing `'testnet'` or `'mainnet'` changes the network object. It does not automatically select a matching deployer and contract registry. Custom deployments must provide explicit identifiers. + +## Sensitive data rules + +Never commit or expose: + +- seed phrases; +- deployer private keys; +- wallet private keys; +- npm authentication tokens; +- GitHub tokens; +- Supabase service-role keys; +- privileged API credentials; +- production multisig signer material. + +Only browser-safe anonymous Supabase configuration belongs in Vite environment variables. Any variable bundled into frontend code must be treated as public. + +## Asset-moving transactions + +Use restrictive post conditions for calls that can transfer, mint, burn, or lock assets. `PostConditionMode.Deny` is the preferred default when all expected asset movements are declared. + +Review: + +- asset type and contract identifier; +- sender and recipient; +- maximum amount; +- mint and burn behavior; +- failure behavior when post conditions do not match; +- whether a permissive mode could hide unexpected movement. + +Do not weaken post conditions merely to make a wallet request pass. + +## Mission reward trust boundary + +The v10 mission compatibility interface accepts a caller-supplied reward argument. The reference application derives rewards from `MISSION_CATALOG`, but frontend-controlled input is not a security boundary. + +Current safeguards and requirements: + +- callers must not enter arbitrary reward values; +- frontend integrations must derive values from the canonical catalog; +- contracts must enforce authorized execution and duplicate-completion rules; +- tests must cover manipulated arguments and unauthorized callers; +- a future contract version should resolve rewards from contract-controlled state. + +## Dependency and supply-chain controls + +- Install with committed lockfiles using `npm ci`. +- Review changes to lockfiles and package publication contents. +- Run public SDK tests and the production build before release. +- Run Clarinet/Simnet tests for included contracts. +- Publish the npm package only from a clean, reviewed commit. +- Do not execute unreviewed deployment scripts with funded keys. +- Treat registry changes as production behavior changes. + +## Administrative operations + +Administrative and upgrade-sensitive actions should use a documented multisig process before production scale. The process should identify: + +- required signers and threshold; +- signer rotation and recovery; +- approved operation types; +- transaction review procedure; +- deployment record retention; +- incident response and emergency communication. + +A single locally stored production key is not the target operating model. ## Current limitations - No independent third-party audit has been completed. -- Administrative operation needs a documented multisig process. +- Administrative operations do not yet have a fully documented multisig process. - No protocol-wide pause mechanism is available. -- Deployed contracts require a new version for logic changes. -- The v10 mission interface keeps caller-supplied reward arguments for compatibility; a future version should resolve rewards from contract-controlled state. +- Deployed contract logic requires a new version for behavioral changes. +- The v10 mission interface retains caller-supplied reward arguments for compatibility. +- The local Clarinet workspace does not contain every contract configured by the mainnet registry. +- The SDK does not currently provide high-level transaction-write helpers. +- Transaction confirmation and activity-history UX can be expanded. + +These limitations must be disclosed to integrators and considered before production use involving meaningful asset value. + +## Required review for sensitive changes + +Changes to any of the following require tests, documentation, and explicit security review: + +- authorization or admin principals; +- mission rewards; +- minting, burning, transfers, or token metadata; +- badge ownership and claim logic; +- contract identifiers; +- network defaults; +- post conditions; +- wallet scopes; +- decoded return shapes used for authorization decisions; +- package exports; +- deployment and release scripts; +- Supabase policies or privileged credentials. + +## Incident response + +When a credible issue is found: + +1. preserve the report and affected identifiers; +2. stop unsafe frontend or release paths when possible; +3. determine whether the issue is frontend, SDK, registry, infrastructure, or immutable contract logic; +4. avoid claiming recovery before confirmed chain state is verified; +5. prepare a versioned contract migration when deployed logic is affected; +6. publish a corrected SDK or frontend release when applicable; +7. document impact, affected versions, remediation, and remaining risk after sensitive details can be disclosed safely. -Changes to authorization, rewards, contract identifiers, or asset presentation require tests and CI validation. +See [Contract Inventory](CONTRACTS.md), [Write Transactions](WRITE_TRANSACTIONS.md), and [Deployment Guide](DEPLOYMENT.md). From 439836b60c90d8c3c78c5bfd9fcbbfd0af5aa18f Mon Sep 17 00:00:00 2001 From: SMOKAHONTAS <69312778+bayyubenjamin@users.noreply.github.com> Date: Thu, 2 Jul 2026 23:15:07 +0700 Subject: [PATCH 10/11] docs: add contribution guide --- CONTRIBUTING.md | 102 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..26baf583 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,102 @@ +# Contributing to StacksOne + +Thank you for improving StacksOne. Keep changes focused, testable, and explicit about which layer owns the behavior. + +## Before starting + +Read: + +- [Development Workflow](docs/WORKFLOW.md); +- [System Architecture](docs/SYSTEM_ARCHITECTURE.md); +- [Contract Inventory](docs/CONTRACTS.md); +- [Security Policy](docs/SECURITY.md). + +For transaction work, also read [Write Transactions](docs/WRITE_TRANSACTIONS.md). + +## Local setup + +```bash +git clone https://github.com/bayyubenjamin/stacksone.git +cd stacksone +npm ci +cp .env.example .env +npm run dev +``` + +Supabase configuration is optional. + +Install contract-test dependencies separately: + +```bash +cd smart-contracts +npm ci +``` + +## Quality gates + +Run from the repository root: + +```bash +npm test +npm run build +npm pack --dry-run +``` + +Run contract tests from `smart-contracts/`: + +```bash +npm test +``` + +A documentation-only change should still verify that commands, paths, imports, contract identifiers, and links match the repository. + +## Contribution rules + +- Import production contract identifiers from `sdk/contracts.js`. +- Do not hard-code deployer addresses in UI components. +- Do not treat wallet submission as transaction confirmation. +- Keep Supabase secondary to confirmed chain state. +- Add tests for public SDK behavior changes. +- Add Simnet tests for Clarity behavior changes. +- Use versioned contract names for incompatible behavior changes. +- Document admin roles, asset movement, post conditions, and migration impact. +- Never commit keys, seed phrases, privileged tokens, or service-role credentials. + +## Pull requests + +A pull request should explain: + +- what changed; +- why it changed; +- affected layers; +- user and developer impact; +- compatibility or migration impact; +- security assumptions; +- checks performed; +- deployment or release work that remains. + +Prefer one coherent change over a large mixture of unrelated cleanup and behavior changes. + +## SDK changes + +When changing a public export, method, normalized return shape, error class, registry key, or helper threshold: + +1. update tests under `tests/`; +2. update `docs/SDK_API.md`; +3. review semantic-version impact; +4. inspect `npm pack --dry-run` output. + +## Contract changes + +When changing Clarity behavior: + +1. update or add Simnet tests; +2. document authorization and error codes; +3. document asset movement and post conditions; +4. state whether the source is local-only, testnet, or configured mainnet; +5. define the version and migration plan; +6. do not update the runtime registry before deployment confirmation. + +## Security issues + +Do not open a public exploit report. Follow [SECURITY.md](SECURITY.md). From 260af9585cab20fc70c3316d0f4203e8b700059e Mon Sep 17 00:00:00 2001 From: SMOKAHONTAS <69312778+bayyubenjamin@users.noreply.github.com> Date: Thu, 2 Jul 2026 23:15:18 +0700 Subject: [PATCH 11/11] docs: expose security policy at repository root --- SECURITY.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..172fe37f --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,7 @@ +# Security + +Do not publish an unresolved vulnerability, private key, exploit transaction, or reproducible attack path in a public issue. + +Use GitHub private vulnerability reporting from the repository Security tab when available. Otherwise contact the repository maintainer through the linked GitHub profile before sharing sensitive reproduction details. + +The full policy, supported package line, trust boundaries, current limitations, and incident-response process are documented in [docs/SECURITY.md](docs/SECURITY.md).