Skip to content
Draft
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
11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,17 @@ on:
branches:
- main

permissions:
contents: read

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
checks:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@v7
Expand Down Expand Up @@ -36,3 +44,6 @@ jobs:

- name: Build
run: pnpm build

- name: Validate Worker bundle
run: pnpm exec wrangler deploy --dry-run --outdir .wrangler/dry-run
7 changes: 2 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ pnpm dev
Before opening a PR, run:

```bash
pnpm lint
pnpm typecheck
pnpm test
pnpm build
pnpm check
```

## Branch and PR Workflow
Expand Down Expand Up @@ -55,7 +52,7 @@ pnpm build

## Community PR Checklist

- [ ] Lint/typecheck/test/build pass locally
- [ ] `pnpm check` passes locally, including the Worker bundle dry-run
- [ ] New behavior covered by tests
- [ ] README/docs updated if needed
- [ ] No breaking API/route changes without notes
Expand Down
15 changes: 10 additions & 5 deletions PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,13 @@
- Deployment risk: explicit Wrangler asset + route config and CI verification.

## Definition of Done
- App runs locally and builds cleanly.
- Cloudflare Worker serves SPA with `/api/*` routes and SPA fallback.
- Universal Inspector + all MVP tools function.
- Tests pass, CI passes, deploy workflow ready.
- README and security/privacy notes complete.
- [x] App runs locally and builds cleanly.
- [x] Cloudflare Worker serves SPA with `/api/*` routes and SPA fallback.
- [x] Universal Inspector and specialized tool suite function.
- [x] Heavy routes are lazy-loaded and large byte views are paged.
- [x] Local file hex viewer includes accessible byte color, search, statistics, and structure maps.
- [x] Binary diff supports synchronized local-file comparison.
- [x] Reusable recipe pipelines expose deterministic intermediate results without persisting payloads.
- [x] Installable offline shell bypasses all API traffic.
- [x] Network diagnostics validate targets and redirects; APIs enforce size/type/rate safeguards.
- [x] Tests, CI, SAST/DAST workflows, OpenAPI, and privacy/security docs are present.
33 changes: 22 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ Desktop - HTTP Signer:
- URL and HTML entity encode/decode
- Unicode inspection (code points, UTF-8 bytes, UTF-16 units)
- JWT inspector with decode warnings and claim highlighting
- Hexdump formatter with offsets and ASCII preview
- Local-file hex viewer with byte-spectrum coloring, search/jump, paging, statistics, and synchronized ASCII
- Clickable binary structure maps for PNG, JPEG, GIF, ZIP, ELF, PE, and PDF files
- Binary/payload diff with two local files, byte-level runs, change navigation, and synchronized selection
- Reusable local recipe pipelines with presets, intermediate values, versioned import/export, and definition-only local saves
- Installable offline app shell; API traffic and payload data are never service-worker cached
- Hash + HMAC helpers via Web Crypto
- Bitwise operations, endianness swap, IPv4/int conversion, timestamp conversion
- Entropy, stats, frequency hints, magic byte detection
Expand Down Expand Up @@ -48,14 +52,17 @@ Desktop - HTTP Signer:
- `tests`: Vitest unit tests for deterministic modules

Core transforms run client-side by default. The Worker is intentionally lean and future-ready.
Every specialized route is lazy-loaded, so opening Hexyr does not download every parser.

## Privacy Model

- Payload transforms are client-side in MVP
- Browser-tool payload transforms are client-side
- No backend persistence
- No payload-content logging
- No Cloudflare KV
- `localStorage` is used only for non-sensitive UI preferences (theme, last selected tool)
- `localStorage` is used only for non-sensitive UI preferences and recipe definitions; recipe inputs and outputs are not saved
- The service worker caches same-origin static assets only and explicitly bypasses `/api/*`
- Calling an integration API or running an opt-in network lookup sends that request to the Worker; this is visibly separate from local browser tools

## Local-First Rationale

Expand Down Expand Up @@ -90,6 +97,8 @@ Local execution keeps interactions faster, lowers edge complexity, and reduces r
- `/tool/hash`
- `/tool/bitwise`
- `/tool/hexdump`
- `/tool/diff`
- `/tool/recipe`
- `/tool/dns`
- `/tool/webhook`
- `/tool/har`
Expand Down Expand Up @@ -161,8 +170,8 @@ pnpm preview
## Deploy to Cloudflare Workers

1. Set secrets or env vars:
- `CLOUDFLARE_API_TOKEN`
- `CLOUDFLARE_ACCOUNT_ID`
- `CLOUDFLARE_API_TOKEN`
- `CLOUDFLARE_ACCOUNT_ID`
2. Authenticate Wrangler if needed:

```bash
Expand Down Expand Up @@ -235,14 +244,16 @@ Includes deterministic coverage for encoding, detection, parsing, entropy, magic
- JWT decode is **not** signature verification.
- Do not treat decoded JWT payloads as trusted unless signature and claims are validated in your own auth context.
- Avoid pasting production secrets into third-party tools; Hexyr is built to keep this local-first.
- Worker APIs require JSON, cap request bodies at 1 MiB, return `no-store`, use defense-in-depth security headers, and rate-limit tool calls per runtime instance.
- Network probes reject local/private/reserved targets, credentials, nonstandard ports, unsafe schemes, and unsafe redirect destinations.
- The in-memory Worker limiter is best-effort per isolate; production abuse controls should also be configured with Cloudflare Rate Limiting.

## Roadmap Ideas
## Optional Future Extensions

- Structured compare mode for two payloads
- Optional local-only encrypted workspace snapshots
- Additional file signature and container format coverage
- Advanced command palette and keyboard workflows
- Large payload virtualization improvements
- More deep container parsers (Mach-O, WebAssembly, SQLite, PCAPNG)
- Multi-edit alignment for inserted/deleted binary ranges
- Opt-in encrypted workspace snapshots with an explicit passphrase
- Signed, shareable recipe packs that never include payload data

## License

Expand Down
7 changes: 7 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Hexyr exposes a compact integration API on the Worker.
- Base URL: `https://hexyr.com`
- OpenAPI: `https://hexyr.com/openapi.json`

All POST endpoints require `Content-Type: application/json`, accept at most 1 MiB, return API
responses with `Cache-Control: no-store`, and are subject to request limiting. API calls are remote
operations; unlike browser-only tools, their request bodies are sent to the Worker.

## Health and Discovery

### `GET /api/health`
Expand Down Expand Up @@ -66,6 +70,9 @@ curl -s https://hexyr.com/api/tools/dns-tool \
```

For probe-limited tools (like Ping/Trace/TCP checks), the response includes an explanatory note plus a local shell command suggestion.
Targets must be fully qualified public hostnames or public IPv4 addresses. Private/reserved
addresses, local names, credentials, unsafe schemes, custom ports, and unsafe redirect
destinations are rejected.

### `POST /api/tools/webhook-verify`

Expand Down
3 changes: 3 additions & 0 deletions docs/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ pnpm run deploy

- Keep Worker logic lean and deterministic.
- No KV bindings are configured.
- Configure Cloudflare Rate Limiting for `/api/tools/*`; the built-in limiter is per Worker isolate.
- Keep the CSP and private-network target protections enabled when adding new API or probe routes.
- Bump the cache name in `public/sw.js` when a service-worker caching policy changes.
9 changes: 9 additions & 0 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,14 @@ pnpm preview

- `/inspect` Universal Inspector
- `/tool/*` specialized developer tools
- `/tool/hexdump` local file and structured binary viewer
- `/tool/diff` binary/payload and two-file diff
- `/tool/recipe` reusable local transform pipelines
- `/api/health` service status
- `/api/meta` runtime metadata

## Offline install

Run a production build or open the deployed site once, then install Hexyr from the browser's app
menu. Static assets and tool chunks are cached as they are opened; network tools still require a
connection.
27 changes: 24 additions & 3 deletions docs/privacy-security.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,22 @@

## Privacy model

- Transforms run client-side by default.
- Browser transforms, recipes, binary inspection, and local-file diffing run client-side.
- Payload contents are not persisted server-side.
- No Cloudflare KV is used in MVP.
- `localStorage` stores only non-sensitive UI preferences.
- No Cloudflare KV or database is used.
- `localStorage` stores only non-sensitive UI preferences and recipe definitions. Recipe payloads,
intermediate values, and outputs are not stored.
- The service worker caches static same-origin app assets only. It bypasses `/api/*` and never
caches API traffic or user payloads.

## Remote operations

Calling `/api/*` directly sends the supplied request body to the Worker. Opt-in DNS, RDAP, and HTTP
reachability tools send the requested public target to the Worker and, where required, an upstream
resolver or registry. These paths are separate from local browser transforms.

Do not send production secrets to an API endpoint unless that remote processing is intentional.
The browser Webhook Verifier performs its normal verification locally.

## JWT caveat

Expand All @@ -15,6 +27,15 @@ JWT decoding in Hexyr is display-only and does not verify signatures.

- Worker enforces HTTPS redirects.
- HSTS is enabled for strict transport.
- Responses include CSP, clickjacking, MIME-sniffing, referrer, permissions, and opener/resource
isolation policies.
- Tool APIs require JSON, cap bodies at 1 MiB, set `Cache-Control: no-store`, and apply a
best-effort per-isolate request limiter.
- Network tools reject private/reserved targets, local hostnames, credentials, unsafe schemes,
custom ports, and redirects to unsafe destinations.

For public production traffic, configure Cloudflare Rate Limiting in addition to the in-process
limiter; Worker isolates do not share process memory.

## Security automation

Expand Down
26 changes: 25 additions & 1 deletion docs/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,42 @@ Paste unknown payloads, get format detection, warnings, entropy hints, and fast
- Text <-> Hex / Base64 / Binary transforms
- URL encode/decode and HTML entities
- Compression/decompression (gzip/deflate, auto-decompress fallback)
- Local Recipe Pipeline:
- Chain deterministic encoders, decoders, JSON steps, and gzip transforms
- Inspect every intermediate value and the character-count change at each step
- Load built-in presets, save definition-only recipes locally, or import/export versioned JSON
- Formatter Lab (expand/minify/validate JSON/YAML/TOML/XML/INI/SQL/HTTP)
- ASCII Art Generator (text fonts + image-to-ASCII)

## Inspection tools

- JWT inspector, Hexdump, Unicode explorer
- JWT inspector and Unicode explorer
- Hex Viewer:
- Open or drop local files without uploading them
- 18-group byte-spectrum coloring (leading nibble plus distinct `00` and `ff`)
- Semantic and color-free display modes
- Hex/text search, offset jump, paged rendering, byte statistics, and synchronized ASCII selection
- Clickable structure overlays for PNG, JPEG, GIF, ZIP, ELF, PE, and PDF containers
- Binary and Payload Diff:
- Strict text/hex/base64 decoding without silent fallback
- Two-file local comparison up to 32 MiB per side
- Byte-level change runs, synchronized selection, paging, and next/previous change navigation

The byte-spectrum approach is inspired by Alice Pellerin's
[“your hex editor should color-code bytes”](https://simonomi.dev/blog/color-code-your-bytes/).

- X.509 inspector, TLS verifier, ASN.1/DER viewer
- HAR inspector, Cookie analyzer, Schema validators
- DNS Tools:
- Zone formatter/validator
- Lookup toolkit (MX, TXT, DMARC, SPF, RDAP/Whois, blacklist, domain health, and related DNS records)

## Offline use

Hexyr can be installed as a PWA. The app shell and tool chunks you have opened are available
offline. The service worker does not cache API requests, API responses, or payloads. Network tools
show normal connection errors while offline; local tools continue to work.

## Crypto and utility tools

- Hash/HMAC and HTTP signer
Expand Down
6 changes: 6 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,11 @@ export default tseslint.config(
globals: globals.serviceworker,
},
},
{
files: ['public/sw.js'],
languageOptions: {
globals: globals.serviceworker,
},
},
prettier,
);
2 changes: 2 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
<link rel="canonical" href="https://hexyr.com/" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="manifest" href="/manifest.webmanifest" />
<link rel="apple-touch-icon" href="/icons/hexyr-mark.svg" />
<meta name="theme-color" content="#07090d" />
<meta
name="description"
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hexyr",
"version": "0.1.0",
"version": "1.0.0",
"private": true,
"license": "Apache-2.0",
"type": "module",
Expand All @@ -13,6 +13,7 @@
"typecheck": "tsc --noEmit",
"test": "vitest run",
"test:watch": "vitest",
"check": "pnpm lint && pnpm typecheck && pnpm test && pnpm build && pnpm exec wrangler deploy --dry-run --outdir .wrangler/dry-run",
"deploy": "pnpm build && pnpm exec wrangler deploy --domain hexyr.com --domain docs.hexyr.com",
"worker:dev": "wrangler dev"
},
Expand Down
40 changes: 40 additions & 0 deletions public/manifest.webmanifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "Hexyr — Human Developer Toolkit",
"short_name": "Hexyr",
"description": "A local-first toolkit for inspecting, decoding, comparing, and transforming developer payloads.",
"id": "/",
"start_url": "/inspect",
"scope": "/",
"display": "standalone",
"background_color": "#07090d",
"theme_color": "#07090d",
"categories": ["developer", "utilities", "productivity"],
"icons": [
{
"src": "/icons/hexyr-mark.svg",
"sizes": "any",
"type": "image/svg+xml",
"purpose": "any maskable"
}
],
"shortcuts": [
{
"name": "Universal Inspector",
"short_name": "Inspect",
"url": "/inspect",
"icons": [{ "src": "/icons/hexyr-mark.svg", "sizes": "any", "type": "image/svg+xml" }]
},
{
"name": "Hex Viewer",
"short_name": "Hex Viewer",
"url": "/tool/hexdump",
"icons": [{ "src": "/icons/hexyr-mark.svg", "sizes": "any", "type": "image/svg+xml" }]
},
{
"name": "Recipe Pipeline",
"short_name": "Recipes",
"url": "/tool/recipe",
"icons": [{ "src": "/icons/hexyr-mark.svg", "sizes": "any", "type": "image/svg+xml" }]
}
]
}
Loading