Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,21 @@ REDIS_URL=redis://localhost:6379
AI_URL=http://localhost:8000
AI_SERVICE_TOKEN=change-me-to-a-32-char-plus-random-secret

# ─── Stellar ────────────────────────────────────────────────────────────────
# STELLAR_NETWORK=testnet
# STELLAR_RPC_URL=https://soroban-testnet.stellar.org
# ─── Stellar anchoring ──────────────────────────────────────────────────────
# Evidence is anchored on the evidence_anchor_registry contract. Pick ONE way to sign.
#
# Option 1 — in-process signer (the worker signs and submits itself):
# STELLAR_SIGNER_SECRET=<secret_key> # testnet key. Must be the registry's controller. Never commit it.
# STELLAR_EVIDENCE_ANCHOR_CONTRACT=<contract_id>
# STELLAR_CUSTODY_CONTRACT=<contract_id>
# STELLAR_SIGNER_SECRET=<secret_key> # never commit this
# STELLAR_ANCHOR_SERVICE_URL= # optional sidecar signing service
# STELLAR_RPC_URL=https://soroban-testnet.stellar.org
# STELLAR_NETWORK=testnet # only testnet is supported
#
# Option 2 — external signing service (takes priority if set):
# STELLAR_ANCHOR_SERVICE_URL=
# STELLAR_SIGNER_TOKEN=<bearer_token>
#
# With neither configured, anchor jobs stay pending and are retried.
# STELLAR_HORIZON_URL=https://horizon-testnet.stellar.org # used to confirm anchors

# ─── Malware scanning (ClamAV) ──────────────────────────────────────────────
CLAMAV_HOST=localhost
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@ jobs:
- run: pnpm prisma generate
env:
DATABASE_URL: postgresql://user:pass@localhost:5432/ci
- run: pnpm format:check
- run: pnpm typecheck
- run: pnpm build
- run: pnpm test
4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dist
node_modules
prisma/migrations
pnpm-lock.yaml
7 changes: 7 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"singleQuote": true,
"semi": true,
"printWidth": 100,
"trailingComma": "all",
"arrowParens": "avoid"
}
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Changelog

## 0.2.0 — 2026-10-09

### Added
- **Stellar anchor signer** (`src/anchor.ts`). The worker can now build, sign,
and submit the `anchor` call on the evidence anchor registry itself, using
`STELLAR_SIGNER_SECRET` and `STELLAR_EVIDENCE_ANCHOR_CONTRACT`. Previously
anchoring required an external signing service that did not exist, so the
`stellar-anchor` job could never complete. The external service is still
supported and takes priority when configured. Retries are safe because the
contract treats an identical anchor as a no-op.
- 49 new tests (10 to 59): manifests, both anchor clients, environment
selection, wallet-signature verification, role permissions, hashing, and
claim validation.
- Prettier, with `format`, `format:check`, and a CI step.

### Fixed
- `permitted()` threw a `TypeError` for role names such as `__proto__` or
`constructor`, which resolved through `Object.prototype`. It now denies them.
- The security contact address in the README and SECURITY.md had a typo
(`gmaill.com`), so vulnerability reports could not be delivered.

### Changed
- Reformatted all source. The worker and API were written as single very long
lines (up to 800 characters), which made review impractical. No behavior
change: the same tests passed before and after.
- The duplicated evidence and attestation anchor code in the worker now shares
one implementation.
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,23 @@ pnpm worker # background job worker, separate process
```

```bash
pnpm build # tsc
pnpm test # unit tests (node:test)
pnpm build # tsc
pnpm test # unit tests (node:test)
pnpm typecheck
pnpm format:check # prettier
```

## Stellar anchoring

After evidence is processed, the worker records a SHA-256 of a manifest (digests and opaque references only, never evidence content) on the `evidence_anchor_registry` contract from [`afterprint-contracts`](https://github.com/Afterprint/afterprint-contracts). Choose a signing method in `.env`:

| Method | Set | Notes |
|---|---|---|
| In-process | `STELLAR_SIGNER_SECRET`, `STELLAR_EVIDENCE_ANCHOR_CONTRACT` | The worker builds, signs, and submits the Soroban transaction. The key must be the registry's controller. Testnet only. |
| Signing service | `STELLAR_ANCHOR_SERVICE_URL`, `STELLAR_SIGNER_TOKEN` | Takes priority when set. |

With neither set, anchor jobs stay pending and retry, so nothing is lost. Retrying is safe: the contract treats an identical anchor as a no-op and rejects a conflicting one. See [`src/anchor.ts`](./src/anchor.ts).

## Contributing

See [CONTRIBUTING.md](./CONTRIBUTING.md) for the workflow and coding standards, and [SECURITY.md](./SECURITY.md) to report a vulnerability privately.
Expand All @@ -63,7 +75,7 @@ See [CONTRIBUTING.md](./CONTRIBUTING.md) for the workflow and coding standards,
| | |
|---|---|
| **GitHub** | [@helloworld1-star](https://github.com/helloworld1-star) |
| **Email** | chijiokejoseph20242@gmaill.com |
| **Email** | devt14985@gmail.com |

---

Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This service has **not** undergone an independent security audit. It's deployed

## Reporting a vulnerability

Email **chijiokejoseph20242@gmaill.com** with a description of the issue and reproduction steps. Do not open a public GitHub issue for security vulnerabilities.
Email **devt14985@gmail.com** with a description of the issue and reproduction steps. Do not open a public GitHub issue for security vulnerabilities.

You should get an acknowledgement within 5 business days. Once a fix is available, we'll coordinate disclosure timing with you.

Expand Down
33 changes: 18 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "afterprint-api",
"version": "0.1.0",
"version": "0.2.0",
"private": true,
"packageManager": "pnpm@10.17.1",
"scripts": {
Expand All @@ -13,34 +13,37 @@
"db:generate": "prisma generate",
"db:migrate": "prisma migrate deploy",
"seed": "node --import tsx scripts/seed.ts",
"worker": "node dist/worker.js"
"worker": "node dist/worker.js",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"scripts/**/*.ts\"",
"format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\" \"scripts/**/*.ts\""
},
"dependencies": {
"@aws-sdk/client-s3": "^3.890.0",
"@aws-sdk/s3-request-presigner": "^3.890.0",
"@fastify/cookie": "^11.0.0",
"@fastify/rate-limit": "^10.0.0",
"@fastify/static": "^10.1.2",
"@nestjs/common": "^12.0.0",
"@nestjs/core": "^12.0.0",
"@nestjs/platform-fastify": "^12.0.0",
"@nestjs/swagger": "^12.0.0",
"@fastify/cookie": "^11.0.0",
"@fastify/rate-limit": "^10.0.0",
"@fastify/static": "^10.1.2",
"@prisma/client": "7.10.0",
"@prisma/adapter-pg": "7.10.0",
"pg": "^8.16.0",
"@prisma/client": "7.10.0",
"@stellar/stellar-sdk": "^17.0.0",
"bullmq": "^6.0.0",
"ioredis": "^5.7.0",
"@aws-sdk/client-s3": "^3.890.0",
"@aws-sdk/s3-request-presigner": "^3.890.0",
"@stellar/stellar-sdk": "^17.0.0",
"zod": "^4.1.0",
"jose": "^6.1.0",
"pg": "^8.16.0",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.2",
"jose": "^6.1.0"
"zod": "^4.1.0"
},
"devDependencies": {
"@types/node": "^24.0.0",
"@types/pg": "^8.15.0",
"prettier": "^3.9.9",
"prisma": "7.10.0",
"tsx": "^4.20.0",
"typescript": "^5.9.2",
"@types/node": "^24.0.0",
"@types/pg": "^8.15.0"
"typescript": "^5.9.2"
}
}
10 changes: 10 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading