{"_id":"@api-policy/hono","_rev":"7-44f592aec747b7ec673c4903b0b3aa59","name":"@api-policy/hono","dist-tags":{"latest":"3.1.1"},"versions":{"1.0.0":{"name":"@api-policy/hono","version":"1.0.0","keywords":["hono","api-policy","auth","permission","middleware","framework-adapter"],"author":{"name":"minhtaimc"},"license":"MIT","_id":"@api-policy/hono@1.0.0","maintainers":[{"name":"minhtaimc","email":"minhtaimc@gmail.com"}],"dist":{"shasum":"fd3c785a1503d13c19a6d643bc96c23fe30a123a","tarball":"https://registry.npmjs.org/@api-policy/hono/-/hono-1.0.0.tgz","fileCount":62,"integrity":"sha512-6i1zp5szmSlTxhk91dXl4vVvU7tfw6y37vGNmdcXUldOcDRwN9+V3DHtKMLIujPT5j6UDH3YdvGVeZ4waqvRmA==","signatures":[{"sig":"MEUCIQDgcPaNBzpeKi5Z2X4R6Yf+wTbOoV8wUDW1VQRtU0fgwAIgfNTKyjPf4p88gpSSNHada8TK3ksMh/m4fRxSI135PA4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":98344},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"c7f2fd5117e9eddda25427c587be46fa837a4dae","scripts":{"dev":"tsc --watch","test":"vitest run --passWithNoTests","build":"tsc","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","type-check":"tsc --noEmit"},"_npmUser":{"name":"minhtaimc","email":"minhtaimc@gmail.com"},"_npmVersion":"11.6.2","description":"Hono.js adapter for API Policy. Auth middleware, permissions, routing.","directories":{},"_nodeVersion":"24.11.1","dependencies":{"zod":"^4.3.6","hono":"^4.12.5","jose":"^6.2.0","ts-micro-result":"^3.3.0","@api-policy/server":"workspace:*"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.18","typescript":"^5.9.3","@types/node":"^25.3.5"},"peerDependencies":{"hono":">=4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/hono_1.0.0_1773067901498_0.9289969743479205","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@api-policy/hono","version":"1.1.0","keywords":["hono","api-policy","auth","permission","middleware","framework-adapter"],"author":{"name":"minhtaimc"},"license":"MIT","_id":"@api-policy/hono@1.1.0","maintainers":[{"name":"minhtaimc","email":"minhtaimc@gmail.com"}],"dist":{"shasum":"6100a544f412d6fb5000ab073f05b4bb07ecec84","tarball":"https://registry.npmjs.org/@api-policy/hono/-/hono-1.1.0.tgz","fileCount":62,"integrity":"sha512-tmp1PDlbIcrym3DIn1Ug4TxqJDQH5VVT8/XWrGKdU6fbxmJxMjDYCv7YkxCElqiHKzuCPt9cdTC+GsZ8KaB2eQ==","signatures":[{"sig":"MEUCIFEFQftLKIJVZR7Q/mKK9hTOVL8o8Nn7i5CaTyh5V5MbAiEAqiUV64IB+Rg7RjXZ64M8kIod7ZiNhVEaftlnIoIDHQc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":99141},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"c6156cd16738d6032c98421b5b2e2447c1d4b1cc","scripts":{"dev":"tsc --watch","test":"vitest run --passWithNoTests","build":"tsc","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","type-check":"tsc --noEmit"},"_npmUser":{"name":"minhtaimc","email":"minhtaimc@gmail.com"},"_npmVersion":"11.6.2","description":"Hono.js adapter for API Policy. Auth middleware, permissions, routing.","directories":{},"_nodeVersion":"24.11.1","dependencies":{"hono":"^4.12.5","jose":"^6.2.0","ts-micro-result":"^3.3.0","@api-policy/server":"workspace:*"},"_hasShrinkwrap":false,"devDependencies":{"zod":"^4.3.6","vitest":"^4.0.18","typescript":"^5.9.3","@types/node":"^25.3.5"},"peerDependencies":{"hono":">=4.0.0"},"peerDependenciesMeta":{"zod":{"optional":true},"arktype":{"optional":true},"valibot":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/hono_1.1.0_1773070837997_0.06490385241962882","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"@api-policy/hono","version":"1.1.1","keywords":["hono","api-policy","auth","permission","middleware","framework-adapter"],"author":{"name":"minhtaimc"},"license":"MIT","_id":"@api-policy/hono@1.1.1","maintainers":[{"name":"minhtaimc","email":"minhtaimc@gmail.com"}],"dist":{"shasum":"62f32725e84e44e2775f4ab67e4862eeb3f9e218","tarball":"https://registry.npmjs.org/@api-policy/hono/-/hono-1.1.1.tgz","fileCount":62,"integrity":"sha512-U0SV7SJBkeVsHlJUbmnZbVYnO5gCEWiMAbVj6T1RWC97092jWFgqSjmrHK2YYGf9/p4zQwV+WrrMmFm8OFX9OA==","signatures":[{"sig":"MEYCIQCoHFC1BY7nuaysZyvTgZ7kWu/DuZ7Af1BRoqUMPDRQ8QIhAIeXJgKVbjHudepnkH5pHp6lvIiCD2qgpo6b9CFqmvxc","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":99136},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"1dfb68d711990705804119c4cdce30bcd56a3656","scripts":{"dev":"tsc --watch","test":"vitest run --passWithNoTests","build":"tsc","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","type-check":"tsc --noEmit"},"_npmUser":{"name":"minhtaimc","email":"minhtaimc@gmail.com"},"_npmVersion":"11.6.2","description":"Hono.js adapter for API Policy. Auth middleware, permissions, routing.","directories":{},"_nodeVersion":"24.11.1","dependencies":{"hono":"^4.12.5","jose":"^6.2.0","ts-micro-result":"^3.3.0","@api-policy/server":"^1.0.1"},"_hasShrinkwrap":false,"devDependencies":{"zod":"^4.3.6","vitest":"^4.0.18","typescript":"^5.9.3","@types/node":"^25.3.5"},"peerDependencies":{"hono":">=4.0.0"},"peerDependenciesMeta":{"zod":{"optional":true},"arktype":{"optional":true},"valibot":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/hono_1.1.1_1773102339900_0.8550308714124304","host":"s3://npm-registry-packages-npm-production"}},"1.1.2":{"name":"@api-policy/hono","version":"1.1.2","keywords":["hono","api-policy","auth","permission","middleware","framework-adapter"],"author":{"name":"minhtaimc"},"license":"MIT","_id":"@api-policy/hono@1.1.2","maintainers":[{"name":"minhtaimc","email":"minhtaimc@gmail.com"}],"dist":{"shasum":"9132237ac1ede9278a8288db69b0b41d9211a562","tarball":"https://registry.npmjs.org/@api-policy/hono/-/hono-1.1.2.tgz","fileCount":62,"integrity":"sha512-1+V3fuvsEhAKOUcA6+Mm5CAUXoHQZOY5YIuJESuz9rc0AvnvSwTIzndnx9dUnlmRSt7KyHSgSainNuEykHyy/Q==","signatures":[{"sig":"MEUCIQCdRUSPJCSnODFePWtWBtab8ZL5fd5f4VLDvyOXkgqP+wIgGN1nO5l5YuIH1Ua4sGazVYN0uNjXkoqBtu82YeaNbVE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":103726},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"1dfb68d711990705804119c4cdce30bcd56a3656","scripts":{"dev":"tsc --watch","test":"vitest run --passWithNoTests","build":"tsc","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","type-check":"tsc --noEmit"},"_npmUser":{"name":"minhtaimc","email":"minhtaimc@gmail.com"},"_npmVersion":"11.6.2","description":"Hono.js adapter for API Policy. Auth middleware, permissions, routing.","directories":{},"_nodeVersion":"24.11.1","dependencies":{"hono":"^4.12.5","jose":"^6.2.0","ts-micro-result":"^3.3.0","@api-policy/server":"^1.0.2"},"_hasShrinkwrap":false,"devDependencies":{"zod":"^4.3.6","vitest":"^4.0.18","typescript":"^5.9.3","@types/node":"^25.3.5"},"peerDependencies":{"hono":">=4.0.0"},"peerDependenciesMeta":{"zod":{"optional":true},"arktype":{"optional":true},"valibot":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/hono_1.1.2_1773107103164_0.04368838768348682","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@api-policy/hono","version":"2.0.0","keywords":["hono","api-policy","auth","permission","middleware","framework-adapter"],"author":{"name":"minhtaimc"},"license":"MIT","_id":"@api-policy/hono@2.0.0","maintainers":[{"name":"minhtaimc","email":"minhtaimc@gmail.com"}],"dist":{"shasum":"2384739182a8c94edf1ee74562a4cd16a2481246","tarball":"https://registry.npmjs.org/@api-policy/hono/-/hono-2.0.0.tgz","fileCount":62,"integrity":"sha512-E8Vxytnaac96/GhKjIwOnm5OYYs7e94PIVPRj/Ihxet0UaoaCeKsMz4sECKr2cj0Wgsg2QIDhlvTEsvXBO1Kpg==","signatures":[{"sig":"MEUCIQCj68XI2jx5duKCO8uI0A+l9N67NH8Xuaici1MjhwuAAgIgaZ2sVcAl1DemfrB6QX00nbwUgQFH1pot/m4cdmcF6xE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":102120},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"f327e84a65c54d79fed8e22c01c2a5993fc74529","scripts":{"dev":"tsc --watch","test":"vitest run --passWithNoTests","build":"tsc","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","type-check":"tsc --noEmit"},"_npmUser":{"name":"minhtaimc","email":"minhtaimc@gmail.com"},"_npmVersion":"11.6.2","description":"Hono.js adapter for API Policy. Auth middleware, permissions, routing.","directories":{},"_nodeVersion":"24.11.1","dependencies":{"hono":"^4.12.5","jose":"^6.2.0","ts-micro-result":"^3.3.0","@api-policy/server":"^2.0.0"},"_hasShrinkwrap":false,"devDependencies":{"zod":"^4.3.6","vitest":"^4.0.18","typescript":"^5.9.3","@types/node":"^25.3.5"},"peerDependencies":{"hono":">=4.0.0"},"peerDependenciesMeta":{"zod":{"optional":true},"arktype":{"optional":true},"valibot":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/hono_2.0.0_1773299855300_0.738624836182818","host":"s3://npm-registry-packages-npm-production"}},"3.1.0":{"name":"@api-policy/hono","version":"3.1.0","keywords":["hono","api-policy","auth","permission","middleware","framework-adapter"],"author":{"name":"minhtaimc"},"license":"MIT","_id":"@api-policy/hono@3.1.0","maintainers":[{"name":"minhtaimc","email":"minhtaimc@gmail.com"}],"dist":{"shasum":"f178a0b8ff6df84d54bd526a3f226b8c4e04c18c","tarball":"https://registry.npmjs.org/@api-policy/hono/-/hono-3.1.0.tgz","fileCount":62,"integrity":"sha512-navMQbkUqX+qqOQx31kIuXU6ZwljNfw8L8oFH0LHrbBel6vFsKXIMaTsq5nnldNEYQTfSzpUkks8gjsz7FKubg==","signatures":[{"sig":"MEQCIBXmcx5IZtbs1RAiqOBXbZMqXLuZg4o3zltGY/RDv1/RAiAECtIKNJWAKOuZ7lq0BJRc6ANKtbJisUaF9Vg3qvhAAg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":101358},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"16ba5dc244324cebdcfc88b4c02266c9b22f4121","scripts":{"dev":"tsc --watch","test":"vitest run --passWithNoTests","build":"tsc","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","type-check":"tsc --noEmit"},"_npmUser":{"name":"minhtaimc","email":"minhtaimc@gmail.com"},"_npmVersion":"11.12.1","description":"Hono.js adapter for API Policy. Auth middleware, permissions, routing.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"hono":"^4.12.25","jose":"^6.2.3","ts-micro-result":"^3.3.0","@api-policy/server":"3.1.1"},"_hasShrinkwrap":false,"devDependencies":{"zod":"^4.4.3","vitest":"^4.1.8","typescript":"^6.0.3","@types/node":"^25.9.3"},"peerDependencies":{"hono":">=4.0.0"},"peerDependenciesMeta":{"zod":{"optional":true},"arktype":{"optional":true},"valibot":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/hono_3.1.0_1781191784943_0.32811351090594076","host":"s3://npm-registry-packages-npm-production"}},"3.1.1":{"name":"@api-policy/hono","version":"3.1.1","description":"Hono.js adapter for API Policy. Auth middleware, permissions, routing.","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsc","dev":"tsc --watch","clean":"rm -rf dist","typecheck":"tsc --noEmit","type-check":"tsc --noEmit","test":"vitest run --passWithNoTests","test:watch":"vitest"},"dependencies":{"@api-policy/server":"3.1.2","hono":"^4.12.25","jose":"^6.2.3","ts-micro-result":"^3.3.0"},"devDependencies":{"@types/node":"^25.9.3","typescript":"^6.0.3","vitest":"^4.1.8","zod":"^4.4.3"},"peerDependencies":{"hono":">=4.0.0"},"peerDependenciesMeta":{"zod":{"optional":true},"valibot":{"optional":true},"arktype":{"optional":true}},"keywords":["hono","api-policy","auth","permission","middleware","framework-adapter"],"author":{"name":"minhtaimc"},"license":"MIT","gitHead":"16ba5dc244324cebdcfc88b4c02266c9b22f4121","_id":"@api-policy/hono@3.1.1","_nodeVersion":"24.15.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-cllovnP0X3qjAUSFXtfBjQNPUJn6f8H4QDBv6/sYwoTNUySObLke1rBZsGRg4JVFTh5ZIJJaxERGf5ryG6dxVg==","shasum":"0ad2ef3bf102423b5065dca46e95fd370564b607","tarball":"https://registry.npmjs.org/@api-policy/hono/-/hono-3.1.1.tgz","fileCount":62,"unpackedSize":101358,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFakuWB3HdkV7vIN9hcW/jiAF4drzjUPO1Qr908nCh6KAiB9TLGrPEYqaw44K9d1mPKQ1WTsSRx0QE6ce7/kFAd04g=="}]},"_npmUser":{"name":"minhtaimc","email":"minhtaimc@gmail.com"},"directories":{},"maintainers":[{"name":"minhtaimc","email":"minhtaimc@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/hono_3.1.1_1781194060587_0.30261780144358474"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-09T14:51:41.401Z","modified":"2026-06-11T16:07:40.862Z","1.0.0":"2026-03-09T14:51:41.647Z","1.1.0":"2026-03-09T15:40:38.147Z","1.1.1":"2026-03-10T00:25:40.115Z","1.1.2":"2026-03-10T01:45:03.319Z","2.0.0":"2026-03-12T07:17:35.486Z","3.1.0":"2026-06-11T15:29:45.084Z","3.1.1":"2026-06-11T16:07:40.726Z"},"author":{"name":"minhtaimc"},"license":"MIT","keywords":["hono","api-policy","auth","permission","middleware","framework-adapter"],"description":"Hono.js adapter for API Policy. Auth middleware, permissions, routing.","maintainers":[{"name":"minhtaimc","email":"minhtaimc@gmail.com"}],"readme":"# @api-policy/hono\n\nHono adapter for [@api-policy/server](../server). Drop-in auth middleware, route factory, and permission enforcement for Hono applications.\n\n```bash\nnpm install @api-policy/hono @api-policy/server hono jose\n```\n\nValidation schemas use [Standard Schema](https://standardschema.dev) — bring your own library (Zod v4, Valibot, ArkType), or use the built-in `slugId` with zero dependencies.\n\n---\n\n## Setup\n\n```ts\nimport { Hono } from 'hono'\nimport {\n  createPolicyPlugin,\n  defineRoute,\n  definePublicRoute,\n  createRouteGroup,\n  combineRoutes,\n  requestContextMiddleware,\n  BOUNDARY,\n  PERM,\n} from '@api-policy/hono'\nimport { ok } from 'ts-micro-result'\n\n// 1. Create plugin (wires up auth + permission engines)\nconst policy = createPolicyPlugin({\n  auth: {\n    jwt: { secret: process.env.JWT_SECRET! },\n  },\n})\n\n// 2. Define routes\nconst listPosts = defineRoute(policy, {\n  method: 'GET',\n  path: '/',\n  auth: true,\n  permission: { resource: 'post', action: PERM.READ, boundary: BOUNDARY.TENANT },\n  handler: async ({ user, query }) => {\n    const posts = await db.posts.list(user!.tenantId)\n    return ok(posts)\n  },\n})\n\nconst health = definePublicRoute(policy, {\n  method: 'GET',\n  path: '/health',\n  handler: async () => ok({ status: 'ok' }),\n})\n\n// 3. Group and mount\nconst app = new Hono()\napp.use('*', requestContextMiddleware)\napp.route('/api/v1', createRouteGroup('/posts', [listPosts]))\napp.route('/api/v1', health)\n```\n\n---\n\n## `createPolicyPlugin`\n\nCreates the auth and permission engines used by all routes.\n\n```ts\nimport { createPolicyPlugin } from '@api-policy/hono'\nimport { createGatewayJwtAuthMethod, createDefaultJwtVerify } from '@api-policy/server'\n\nconst policy = createPolicyPlugin({\n  auth: {\n    // Default methods when route has auth: true\n    defaultMethods: ['jwt', 'apiKey'],\n\n    // JWT — symmetric (HS256) or asymmetric (RS256, ES256, EdDSA)\n    jwt: { secret: process.env.JWT_SECRET! },\n    // jwt: { publicKey: process.env.JWT_PUBLIC_KEY!, algorithm: 'EdDSA' },\n    // jwt: { publicKey: '...', verify: myCustomVerifyFn },  // custom verify\n\n    // API Key\n    apiKey: {\n      lookup: async (key) => {\n        const record = await db.apiKeys.findOne({ key })\n        return record ? { ownerId: record.userId, perms: record.perms, tenantId: record.tenantId } : null\n      },\n    },\n\n    // Custom auth methods (e.g. Gateway JWT for BFF → backend)\n    customMethods: [myCustomAuthMethod],\n  },\n\n  // Custom error → HTTP status codes (merged with system defaults)\n  errorHttpMap: {\n    PRODUCT_NOT_FOUND: 404,\n    PRODUCT_SLUG_EXISTS: 409,\n  },\n})\n\n// policy.auth         → AuthPolicyEngine\n// policy.permission   → PermissionEngine\n// policy.errorHttpMap → merged error→HTTP status map\n```\n\n### Gateway JWT mode (BFF → backend)\n\nIf your service sits behind a BFF (e.g. Cloudflare Worker) that verifies the client JWT and forwards requests with a signed Gateway JWT:\n\n```ts\nimport { createGatewayJwtAuthMethod, createDefaultJwtVerify } from '@api-policy/server'\n\nconst jwtConfig = { secret: process.env.JWT_SECRET! }\n\nconst policy = createPolicyPlugin({\n  auth: {\n    defaultMethods: ['gatewayJwt'],\n    customMethods: [\n      createGatewayJwtAuthMethod({\n        gateway: {\n          publicKeyHex: process.env.BFF_PUBLIC_KEY_HEX,  // omit for local dev\n          expectedIssuer: 'bff-worker',\n          expectedAudience: 'my-backend',\n        },\n        accessJwt: {\n          config: jwtConfig,\n          verifyFn: createDefaultJwtVerify(jwtConfig),\n        },\n      }),\n    ],\n  },\n})\n```\n\n---\n\n## `defineRoute`\n\nBuilds a Hono middleware handler with the full auth pipeline attached.\n\n```ts\nimport { defineRoute, BOUNDARY, PERM } from '@api-policy/hono'\nimport { z } from 'zod'  // or valibot, arktype — any Standard Schema library\n\nconst createPost = defineRoute(policy, {\n  method: 'POST',\n  path: '/',\n  auth: true,                    // use default methods\n  // auth: 'jwt'                 // specific method\n  // auth: ['jwt', 'apiKey']     // try list in order\n  permission: {\n    resource: 'post',\n    action: PERM.WRITE,\n    boundary: BOUNDARY.TENANT,\n    roles: ['editor', 'admin'],  // optional role gate (OR logic by default)\n  },\n  input: {\n    body: z.object({ title: z.string(), content: z.string() }),\n    query: z.object({ draft: z.coerce.boolean().default(false) }),\n  },\n  handler: async ({ user, body, query, tenantContext, traceId }) => {\n    const post = await db.posts.create({ ...body, authorId: user!.id })\n    return ok(post)\n  },\n})\n```\n\n**Handler context (`PolicyContext`):**\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `user` | `UserContext \\| undefined` | Authenticated user (always present on auth routes) |\n| `body` | `TBody` | Validated request body |\n| `query` | `TQuery` | Validated query params |\n| `params` | `TParams` | Validated path params |\n| `tenantContext` | `TenantContext \\| undefined` | Set by `createTenantResolverMiddleware` |\n| `traceId` | `string` | Request trace ID |\n\n**Middleware pipeline (in order):**\n\n```\n1. Auth        → verify credentials, set c.var.authResult\n2. Permission  → roles gate → owner bypass → bitmask → boundary\n3. Validation  → validate body/query/params (Standard Schema — Zod, Valibot, ArkType, or built-in)\n4. Handler     → business logic, returns Result<T>\n```\n\n**Route metadata** is attached to the returned handler:\n\n```ts\ncreatePost.routeMeta  // { method: 'POST', path: '/', authRequired: true }\n```\n\n### `definePublicRoute`\n\nShorthand for routes with no auth (`auth: false` is forced, no permission field):\n\n```ts\nconst health = definePublicRoute(policy, {\n  method: 'GET',\n  path: '/health',\n  handler: async () => ok({ status: 'ok' }),\n})\n```\n\n---\n\n## Route grouping\n\n```ts\nimport { createRouteGroup, combineRoutes } from '@api-policy/hono'\n\n// Group routes under a base path\nconst postRoutes    = createRouteGroup('/posts',    [listPosts, createPost, getPost, deletePost])\nconst productRoutes = createRouteGroup('/products', [listProducts, createProduct])\n\n// Merge groups and mount\nconst app = new Hono()\napp.route('/api/v1', combineRoutes(postRoutes, productRoutes))\n```\n\n`createRouteGroup` registers each route at `basePath + route.path` (e.g. `/posts/:id`). A route with `path: '/'` registers at `basePath` exactly.\n\n---\n\n## Middleware\n\n### Request context\n\nGenerates a `traceId` from `X-Request-ID` / `X-Correlation-ID` headers, or creates a UUID. Mount once globally.\n\n```ts\nimport { requestContextMiddleware, getTraceId } from '@api-policy/hono'\n\napp.use('*', requestContextMiddleware)\n\n// In any handler\nconst traceId = getTraceId(c)\n```\n\n### Tenant resolver\n\nResolves `tenantId` from trusted sources only — never from client-supplied headers.\n\n```ts\nimport { createTenantResolverMiddleware } from '@api-policy/hono'\n\napp.use('*', createTenantResolverMiddleware({\n  // Source 1 (highest priority): JWT (user.tenantId from authResult)\n  // Source 2: domain lookup\n  domainLookup: async (domain) => {\n    return db.domains.findByHost(domain)\n    // Returns: { tenantId: string, storeId?: string } | null\n  },\n  allowDomainFallback: true,\n}))\n\n// In handler\nconst { tenantId, storeId, source } = ctx.tenantContext!\n// source: 'jwt' | 'domain'\n```\n\nFor handlers that require `tenantId` to be non-nullable, use `TenantPolicyContext`:\n\n```ts\nimport type { TenantPolicyContext } from '@api-policy/hono'\n\nhandler: async (ctx: TenantPolicyContext<MyBody>) => {\n  ctx.user.tenantId  // string (not string | undefined)\n}\n```\n\n### Rate limiting\n\n```ts\nimport { createRateLimitMiddleware, createInMemoryRateLimitCheck } from '@api-policy/hono'\n\n// Dev/testing — in-memory sliding window\napp.use('*', createRateLimitMiddleware({\n  checkFn: createInMemoryRateLimitCheck(),\n  defaultLimit: 1000,\n}))\n\n// Production — custom backend (Redis, etc.)\napp.use('*', createRateLimitMiddleware({\n  checkFn: async (tenantId, keyId, limit) => redis.slidingWindow(tenantId, keyId, limit),\n  getKeyIdFn: (c) => c.var.authResult?.method,\n  skipFn: (c) => c.req.path === '/health',\n}))\n```\n\nSets response headers automatically: `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`, `Retry-After`.\n\n### Validation middleware (standalone)\n\n`validate()` accepts any [Standard Schema](https://standardschema.dev) compatible library. Zod is **not** a required dependency.\n\n```ts\nimport { validate, getValidatedParams, getValidatedQuery, slugId } from '@api-policy/hono'\n\n// Zod v4 (optional peer dependency)\nimport { z } from 'zod'\napp.use('/posts/:id', validate({\n  params: z.object({ id: z.string() }),\n  query: z.object({ page: z.coerce.number().default(1) }),\n}))\n\n// Valibot (optional peer dependency)\nimport * as v from 'valibot'\napp.use('/posts/:id', validate({\n  params: v.object({ id: v.string() }),\n}))\n\n// Built-in — zero dependency\napp.use('/posts/:id', validate({ params: slugId }))\n\napp.get('/posts/:id', (c) => {\n  const params = getValidatedParams<{ id: string }>(c)\n  const query  = getValidatedQuery<{ page: number }>(c)\n})\n```\n\nBuilt-in (zero-dependency): `slugId` (lowercase, numbers, hyphens, 1–100 chars), `optionalSlugId`.\n\n---\n\n## HTTP response\n\n`toHttpResponse` is called automatically inside `defineRoute`. Use it directly if building custom handlers.\n\n```ts\nimport { toHttpResponse, setFeatureErrorsHttpMap } from '@api-policy/hono'\n\n// Register app-specific error codes once at startup\nsetFeatureErrorsHttpMap({\n  PRODUCT_NOT_FOUND: 404,\n  PRODUCT_SLUG_EXISTS: 409,\n})\n\n// In a custom handler\nreturn toHttpResponse(c, result, { traceId, successStatus: 201 })\n```\n\n**Success response:**\n```json\n{ \"ok\": true, \"data\": { ... }, \"meta\": { \"traceId\": \"...\", \"params\": { \"timestamp\": \"...\" } } }\n```\n\n**Error response:**\n```json\n{ \"ok\": false, \"errors\": [{ \"code\": \"PERMISSION_DENIED\", \"message\": \"...\" }], \"meta\": { ... } }\n```\n\n---\n\n## Hono context variables\n\nThis package sets the following on Hono's `ContextVariableMap`:\n\n| Key | Type | Set by |\n|-----|------|--------|\n| `requestId` | `string` | `requestContextMiddleware` |\n| `correlationId` | `string` | `requestContextMiddleware` |\n| `authResult` | `HonoAuthResult` | `createAuthMiddleware` |\n| `tenantContext` | `TenantContext` | `createTenantResolverMiddleware` |\n| `validatedData` | `ValidatedData` | `validate` |\n\n```ts\nc.var.authResult?.user       // UserContext\nc.var.tenantContext?.tenantId\nc.var.validatedData?.body\n```\n\n---\n\n## Re-exported from @api-policy/server\n\nAll commonly used exports are available directly from `@api-policy/hono`:\n\n```ts\nimport {\n  PERM, PERM_ALL, BOUNDARY, AUTH_METHOD,\n  createJwtAuthMethod, createApiKeyAuthMethod,\n  createGatewayJwtAuthMethod,\n  createAuthPolicyEngine, createPermissionEngine,\n  Forbidden, AlreadyExists, Conflict, RateLimitExceeded,\n  lintRoutes, validateBuild, createPermissionRegistry,\n} from '@api-policy/hono'\n```\n\n---\n\n## License\n\nMIT\n","readmeFilename":"README.md"}