diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..45d13cb --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,40 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +## Our Standards + +Examples of behavior that contributes to a positive environment: + +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members + +Examples of unacceptable behavior: + +- The use of sexualized language or imagery, and sexual attention or advances of any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information without explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the project maintainer at https://bntvllnt.com or via +[Discord](https://discord.gg/V9yss7VfVT). + +All complaints will be reviewed and investigated promptly and fairly. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1. diff --git a/docs/API.md b/docs/API.md new file mode 100644 index 0000000..621a12b --- /dev/null +++ b/docs/API.md @@ -0,0 +1,93 @@ +# API Reference + +Full API reference for `@vllnt/convex-api-keys`. + +## ApiKeys Class + +```ts +import { ApiKeys } from "@vllnt/convex-api-keys"; +import { components } from "./_generated/api"; + +const apiKeys = new ApiKeys(components.apiKeys, { + prefix: "myapp", // key prefix (default: "vk") + defaultType: "secret", // "secret" | "publishable" (default: "secret") +}); +``` + +## Methods + +### create(ctx, options) + +Create a new API key. Returns the raw key once — only the hash is stored. + +| Param | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | `string` | yes | Display name | +| `ownerId` | `string` | yes | Tenant/org/user ID | +| `type` | `"secret" \| "publishable"` | no | Key type (default from config) | +| `scopes` | `string[]` | no | Permission scopes | +| `tags` | `string[]` | no | Filterable tags | +| `env` | `string` | no | Environment (default: `"live"`) | +| `metadata` | `Record` | no | Arbitrary JSON | +| `remaining` | `number` | no | Finite-use counter | +| `expiresAt` | `number` | no | Expiry timestamp (ms) | + +**Returns:** `{ keyId: string, key: string }` + +### validate(ctx, { key }) + +Validate a key and track usage. Decrements `remaining`, checks rate limits. + +**Returns:** `{ valid: true, keyId, ownerId, type, env, scopes, tags, metadata, remaining }` or `{ valid: false, reason, retryAfter? }` + +**Rejection reasons:** `"malformed"`, `"not_found"`, `"revoked"`, `"disabled"`, `"expired"`, `"exhausted"`, `"rate_limited"` + +### revoke(ctx, { keyId }) + +Permanently revoke a key. Idempotent. + +### revokeByTag(ctx, { ownerId, tag }) + +Bulk revoke all active keys matching a tag. + +**Returns:** `{ revokedCount: number }` + +### rotate(ctx, { keyId, gracePeriodMs? }) + +Create a new key and put the old key in grace period. Both keys validate during the grace period. + +| Param | Type | Default | Description | +|-------|------|---------|-------------| +| `gracePeriodMs` | `number` | `3600000` (1h) | Grace period duration | + +**Returns:** `{ newKeyId, newKey, oldKeyExpiresAt }` + +### list(ctx, { ownerId, env?, status? }) + +List keys for an owner. No secrets exposed. + +### listByTag(ctx, { ownerId, tag }) + +List keys matching a specific tag. + +### update(ctx, { keyId, name?, scopes?, tags?, metadata? }) + +Update key metadata in-place without rotation. + +### disable(ctx, { keyId }) + +Temporarily disable a key. Reversible via `enable()`. + +### enable(ctx, { keyId }) + +Re-enable a disabled key. + +### getUsage(ctx, { keyId, period? }) + +Get usage analytics for a key. + +**Returns:** `{ total: number, remaining?: number, lastUsedAt?: number }` + +### configure(ctx, { cleanupIntervalMs?, defaultExpiryMs? }) + +Set runtime configuration for the component.