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
15 changes: 15 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
trim_trailing_whitespace = true

[*.py]
indent_size = 4

[Makefile]
indent_style = tab
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @hellopaywaz
24 changes: 0 additions & 24 deletions .github/workflows/codeql-analysis.yml

This file was deleted.

12 changes: 12 additions & 0 deletions .github/workflows/samples-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ jobs:
with:
node-version: 20

- name: Install root tooling
run: npm ci

- name: Lint (golden command)
run: npm run lint

- name: Test (golden command)
run: npm test

- name: Build (golden command)
run: npm run build

# -----------------------
# Payments sample checks
# -----------------------
Expand Down
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.DS_Store
node_modules/
*.log
*.tmp
.env
.env.local
.npmrc
coverage/
dist/
build/
/.cache/
/.nyc_output/
__pycache__/
*.pyc
*.pyo
43 changes: 43 additions & 0 deletions HEALTH.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Repository Health

**Overall score: 65/100** — Samples now have baseline tooling, ownership, and a minimal webhook unit test, but dependency pinning and release/ops practices remain light.

## Category scores
- CI/Build Reproducibility (25): **18/25** — GitHub Actions runs lint/test/build and a webhook smoke flow, but JavaScript sample dependencies are not lockfile-pinned and Python has no automation.
- Tests/Quality Gates (20): **12/20** — Node webhook signature tests exist; other samples rely on manual runs and have no linting beyond syntax checks.
- Security Baseline (20): **14/20** — SECURITY.md and CodeQL are present and CODEOWNERS added; no secret scanning or dependency audit in CI.
- Release/Packaging (15): **8/15** — No versioning, changelog, or publish flow; samples are not packaged for distribution.
- Documentation/Onboarding (10): **8/10** — README documents golden commands and setup; sample-specific docs are brief and Python onboarding is minimal.
- Ops/Runbooks/Observability (10): **5/10** — Webhook samples log minimally; no health checks or runbooks, which is acceptable for samples but still a gap for production readiness.

## P0 blockers (must-fix)
None detected after this pass.

## P1 risks (should fix soon)
- Lock JavaScript sample dependencies (`javascript/payments`, `javascript/webhooks-node`) with package-locks or pnpm/yarn locks to improve reproducibility.
- Add automated checks for the Python sample (e.g., `python -m compileall python` in CI) so it participates in quality gates.
- Add dependency vulnerability scanning/secret scanning to CI (e.g., `npm audit --production` for JavaScript, GitHub Advanced Security features if available).
- Flesh out release notes/versioning expectations if any sample is intended for reuse beyond ad-hoc demos.

## P2 hygiene (nice-to-have)
- Add lightweight linting (ESLint/Prettier) to the JavaScript samples for style consistency.
- Provide small README sections per sample with explicit env vars and example outputs.
- Add a minimal runbook/operational note for the webhook server sample (expected ports, health endpoint guidance).

## CI status
- `samples-ci.yml`: Node 20 job that runs repo-wide golden commands (`npm run lint`, `npm test`, `npm run build`), then syntax checks and exercises the Node webhook server with a signed webhook smoke test.
- `codeql.yml`: Weekly/PR CodeQL scan for JavaScript/TypeScript with read-only permissions and security-events write.

## Security baseline
- SECURITY.md present with disclosure instructions. License documented in `LICENSE`. `.env.example` keeps secrets placeholder-only.
- No automated secret scanning or dependency audit currently configured. CI permissions are least-privilege for CodeQL; other workflows rely on defaults.

## Release readiness
- No versioning, changelog, or tagged releases. Samples are not published; no artifact pipeline exists.

## Ops readiness
- Webhook samples log to stdout and support secret rotation/tolerance settings via env vars; no health endpoints or runbooks. No monitoring guidance.

## Repo hygiene
- Baseline community files present: README, CONTRIBUTING, CODE_OF_CONDUCT, SECURITY, CODEOWNERS, LICENSE, .editorconfig, .gitignore.
- Samples lack lockfiles and detailed per-sample docs; Python sample lacks dependency metadata.
109 changes: 109 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
Paywaz Proprietary License Agreement
Version 1.0 — © 2025 Paywaz.com LLC

IMPORTANT: This software, documentation, or file set (the “Software”) is the
intellectual property of Paywaz.com LLC (“Paywaz”). By accessing, downloading,
copying, or using the Software, you agree to the terms of this License.

If you do not agree, you must immediately cease all use of the Software.

---

1. GRANT OF LIMITED RIGHT

Paywaz grants you a limited, revocable, non-exclusive, non-transferable,
non-sublicensable license to:

(a) View the Software for informational, evaluation, or integration-planning
purposes;
(b) Use the Software solely for non-commercial internal evaluation;
(c) Reference the Software to assess compatibility with your own systems.

No other rights are granted.

---

2. RESTRICTIONS

Except where explicitly permitted in writing by Paywaz, you MAY NOT:

(a) Copy, modify, distribute, publish, or create derivative works of the Software;
(b) Use the Software for any commercial activity, paid service, production
environment, or merchant processing;
(c) Reverse engineer, decompile, disassemble, or attempt to derive source logic,
data models, API behavior, or internal system architecture;
(d) Remove, alter, or obscure any Paywaz ownership notices;
(e) Redistribute the Software on GitHub or any other platform;
(f) Use the Software to build or improve a competing product or service.

Any unauthorized use terminates this License immediately.

---

3. OWNERSHIP

All rights, title, interest, trademarks, trade secrets, and intellectual property
associated with the Software remain the exclusive property of Paywaz.com LLC.

Nothing in this License transfers or assigns ownership to you.

---

4. NO WARRANTY

The Software is provided “AS IS” with no warranties, express or implied,
including but not limited to warranties of:

– Merchantability
– Fitness for a particular purpose
– Accuracy
– Availability
– Non-infringement

Paywaz disclaims all liability arising from use of the Software.

---

5. LIMITATION OF LIABILITY

To the maximum extent permitted by law, Paywaz shall not be liable for any:

– Direct, indirect, incidental, special, punitive, or consequential damages
– Loss of revenue, profits, data, business opportunity, goodwill
– Security breaches, interruptions, or operational impacts

Use of the Software is entirely at your own risk.

---

6. TERMINATION

Paywaz may revoke this License at any time without notice.
Upon termination, you must immediately cease all use and destroy any copies of
the Software.

---

7. GOVERNING LAW

This License shall be governed by and construed in accordance with the laws of
the State of Delaware, without regard to conflict-of-law principles.

---

8. CONTACT

For commercial licensing, permissions, or partnership inquiries:

Paywaz.com LLC
Email: legal@paywaz.com
Website: https://paywaz.com

---

9. ACCEPTANCE

By accessing or using the Software, you acknowledge that you have read,
understood, and agree to be bound by this License.

© 2025 Paywaz.com LLC — All Rights Reserved.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,23 @@ npm install
npm run start
```

### Golden commands
Run these from the repo root to sanity-check the samples:

```bash
# Parse-check JavaScript samples
npm run lint

# Webhook signature unit tests (node:test)
npm test

# Alias for lint (no compilation required yet)
npm run build

# Run the payments sample (requires PAYWAZ_* env vars)
npm start
```

---

## Requirements
Expand Down
1 change: 1 addition & 0 deletions javascript/webhooks-node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
},
"scripts": {
"start": "node server.mjs",
"test": "node --test",
"test:send": "node send-test-webhook.mjs"
},
"dependencies": {
Expand Down
90 changes: 90 additions & 0 deletions javascript/webhooks-node/test/verify-signature.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import assert from "node:assert/strict";
import { test } from "node:test";
import { signPaywazWebhook } from "../sign-webhook.mjs";
import { verifyPaywazWebhook } from "../verify-signature.mjs";

test("sign + verify succeeds with rotation support", () => {
const rawBody = JSON.stringify({ hello: "world" });
const timestamp = 1_700_000_000;
const secrets = ["whsec_current", "whsec_previous"];

const { signature } = signPaywazWebhook({
rawBody,
secret: secrets[0],
timestamp
});

const originalNow = Date.now;
Date.now = () => timestamp * 1000;

try {
const result = verifyPaywazWebhook({
rawBody,
timestampHeader: String(timestamp),
signatureHeader: signature,
secrets,
toleranceSeconds: 300
});

assert.equal(result.secretIndex, 0);
assert.equal(result.timestamp, timestamp);
} finally {
Date.now = originalNow;
}
});

test("verifies signatures created with previous secrets", () => {
const rawBody = JSON.stringify({ id: "evt_123" });
const timestamp = 1_700_000_123;
const secrets = ["whsec_rotated", "whsec_old"];

const { signature } = signPaywazWebhook({
rawBody,
secret: secrets[1],
timestamp
});

const originalNow = Date.now;
Date.now = () => timestamp * 1000;

try {
const result = verifyPaywazWebhook({
rawBody,
timestampHeader: String(timestamp),
signatureHeader: signature,
secrets,
toleranceSeconds: 300
});

assert.equal(result.secretIndex, 1);
} finally {
Date.now = originalNow;
}
});

test("rejects stale timestamps", () => {
const rawBody = "{}";
const timestamp = 1_700_000_000;
const { signature } = signPaywazWebhook({
rawBody,
secret: "whsec_expired",
timestamp
});

const originalNow = Date.now;
Date.now = () => (timestamp + 1000) * 1000;

try {
assert.throws(() =>
verifyPaywazWebhook({
rawBody,
timestampHeader: String(timestamp),
signatureHeader: signature,
secrets: ["whsec_expired"],
toleranceSeconds: 300
})
);
} finally {
Date.now = originalNow;
}
});
15 changes: 15 additions & 0 deletions package-lock.json

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

19 changes: 19 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "paywaz-samples",
"version": "0.1.0",
"private": true,
"description": "Health-checked Paywaz sample integrations",
"engines": {
"node": ">=20"
},
"scripts": {
"lint": "npm run lint:payments && npm run lint:webhooks-express && npm run lint:webhooks-node",
"lint:payments": "node --check javascript/payments/create-payment.mjs && node --check javascript/payments/get-payment.mjs",
"lint:webhooks-express": "node --check javascript/webhooks-express/server.mjs && node --check javascript/webhooks-express/verify-signature.mjs",
"lint:webhooks-node": "node --check javascript/webhooks-node/server.mjs && node --check javascript/webhooks-node/verify-signature.mjs && node --check javascript/webhooks-node/sign-webhook.mjs && node --check javascript/webhooks-node/send-test-webhook.mjs",
"test": "npm run test:webhooks-node",
"test:webhooks-node": "npm --prefix javascript/webhooks-node test",
"build": "npm run lint",
"start": "node javascript/payments/create-payment.mjs"
}
}