@lastshotlabs/bunshot 0.0.28 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.oclif.manifest.json +1 -1
- package/dist/cli/index.js +0 -0
- package/dist/packages/bunshot-auth/src/lib/credentialStuffing.js +2 -12
- package/dist/packages/bunshot-auth/src/plugin.js +5 -2
- package/dist/src/framework/lib/auditLog.js +1 -1
- package/dist/src/framework/mountOptionalEndpoints.js +28 -11
- package/package.json +44 -6
package/.oclif.manifest.json
CHANGED
package/dist/cli/index.js
CHANGED
|
File without changes
|
|
@@ -200,21 +200,11 @@ export function createCredentialStuffingService(config, repo) {
|
|
|
200
200
|
const ipWindowMs = config.maxAccountsPerIp?.windowMs ?? 15 * 60 * 1000;
|
|
201
201
|
const accountWindowMs = config.maxIpsPerAccount?.windowMs ?? 15 * 60 * 1000;
|
|
202
202
|
const ipCount = await repo.getSetSize(`ip:${ip}`, ipWindowMs);
|
|
203
|
-
if (ipCount >= ipMax)
|
|
204
|
-
try {
|
|
205
|
-
config.onDetected?.({ type: 'ip', key: ip, count: ipCount });
|
|
206
|
-
}
|
|
207
|
-
catch { }
|
|
203
|
+
if (ipCount >= ipMax)
|
|
208
204
|
return true;
|
|
209
|
-
}
|
|
210
205
|
const accountCount = await repo.getSetSize(`account:${identifier}`, accountWindowMs);
|
|
211
|
-
if (accountCount >= accountMax)
|
|
212
|
-
try {
|
|
213
|
-
config.onDetected?.({ type: 'account', key: identifier, count: accountCount });
|
|
214
|
-
}
|
|
215
|
-
catch { }
|
|
206
|
+
if (accountCount >= accountMax)
|
|
216
207
|
return true;
|
|
217
|
-
}
|
|
218
208
|
return false;
|
|
219
209
|
},
|
|
220
210
|
};
|
|
@@ -17,14 +17,17 @@ export function createAuthPlugin(rawConfig) {
|
|
|
17
17
|
const config = validatePluginConfig('bunshot-auth', rawConfig, authPluginConfigSchema);
|
|
18
18
|
// Lifecycle handoff: setupMiddleware resolves this promise once bootstrap
|
|
19
19
|
// completes. Later phases await it — type-safe, no mutable variable.
|
|
20
|
-
// rejectBootstrap is called when setupMiddleware throws so
|
|
21
|
-
//
|
|
20
|
+
// rejectBootstrap is called when setupMiddleware throws so teardown() can
|
|
21
|
+
// detect failure and return early rather than deadlocking on bootstrapReady.
|
|
22
|
+
// The .catch(() => {}) suppresses the unhandled-rejection warning in cases
|
|
23
|
+
// where setupMiddleware throws before teardown() attaches its own catch.
|
|
22
24
|
let resolveBootstrap;
|
|
23
25
|
let rejectBootstrap;
|
|
24
26
|
const bootstrapReady = new Promise((resolve, reject) => {
|
|
25
27
|
resolveBootstrap = resolve;
|
|
26
28
|
rejectBootstrap = reject;
|
|
27
29
|
});
|
|
30
|
+
bootstrapReady.catch(() => { });
|
|
28
31
|
return {
|
|
29
32
|
name: 'bunshot-auth',
|
|
30
33
|
async setupMiddleware(app, frameworkConfig, bus) {
|
|
@@ -49,7 +49,7 @@ function createMemoryAuditLogProvider() {
|
|
|
49
49
|
const memoryLogs = [];
|
|
50
50
|
let evictedEntries = 0;
|
|
51
51
|
let hasWarnedAboutTruncation = false;
|
|
52
|
-
console.warn(`[bunshot] Memory adapter for audit log is capped at ${DEFAULT_MAX_ENTRIES} entries and has no
|
|
52
|
+
console.warn(`[bunshot] Memory adapter for audit log is capped at ${DEFAULT_MAX_ENTRIES} entries and has no eviction — for development/testing only`);
|
|
53
53
|
return {
|
|
54
54
|
async logEntry(entry) {
|
|
55
55
|
try {
|
|
@@ -3,27 +3,44 @@ import { createQueueFactory } from '../lib/queue';
|
|
|
3
3
|
// Implementation
|
|
4
4
|
// ---------------------------------------------------------------------------
|
|
5
5
|
export async function mountOptionalEndpoints(app, coreRoutesDir, jobs, metrics, upload, metricsState, resolvedSecrets) {
|
|
6
|
+
// Security validation runs before infrastructure creation so config errors
|
|
7
|
+
// take priority over missing infrastructure (Redis) errors.
|
|
8
|
+
if (jobs?.statusEndpoint) {
|
|
9
|
+
const jobsAuth = jobs.auth ?? 'none';
|
|
10
|
+
if (jobsAuth === 'none' && !jobs.unsafePublic) {
|
|
11
|
+
if (process.env.NODE_ENV === 'production') {
|
|
12
|
+
throw new Error('[security] jobs.auth is required in production. Set jobs.auth or explicitly set unsafePublic: true with auth: "none".');
|
|
13
|
+
}
|
|
14
|
+
console.warn('[security] /jobs is enabled without auth. Configure jobs.auth for production.');
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
// Queue factory is created lazily — defers Redis validation to first use
|
|
18
|
+
// so the app can start without Redis when using the jobs/metrics endpoints.
|
|
6
19
|
const needsQueueFactory = !!jobs?.statusEndpoint || !!metrics?.queues?.length;
|
|
7
|
-
|
|
8
|
-
|
|
20
|
+
let _cachedFactory;
|
|
21
|
+
function getLazyFactory() {
|
|
22
|
+
if (!_cachedFactory) {
|
|
9
23
|
if (!resolvedSecrets.redisHost) {
|
|
10
24
|
throw new Error('[queue] Jobs/metrics queue helpers require REDIS_HOST via the Bunshot secret bundle at startup.');
|
|
11
25
|
}
|
|
12
|
-
|
|
26
|
+
_cachedFactory = createQueueFactory({
|
|
13
27
|
host: resolvedSecrets.redisHost,
|
|
14
28
|
user: resolvedSecrets.redisUser,
|
|
15
29
|
password: resolvedSecrets.redisPassword,
|
|
16
30
|
});
|
|
17
|
-
}
|
|
31
|
+
}
|
|
32
|
+
return _cachedFactory;
|
|
33
|
+
}
|
|
34
|
+
const queueFactory = needsQueueFactory
|
|
35
|
+
? {
|
|
36
|
+
createQueue: (...args) => getLazyFactory().createQueue(...args),
|
|
37
|
+
createWorker: (...args) => getLazyFactory().createWorker(...args),
|
|
38
|
+
createCronWorker: (...args) => getLazyFactory().createCronWorker(...args),
|
|
39
|
+
cleanupStaleSchedulers: (...args) => getLazyFactory().cleanupStaleSchedulers(...args),
|
|
40
|
+
createDLQHandler: (...args) => getLazyFactory().createDLQHandler(...args),
|
|
41
|
+
}
|
|
18
42
|
: undefined;
|
|
19
43
|
if (jobs?.statusEndpoint) {
|
|
20
|
-
const jobsAuth = jobs.auth ?? 'none';
|
|
21
|
-
if (jobsAuth === 'none' && !jobs.unsafePublic) {
|
|
22
|
-
if (process.env.NODE_ENV === 'production') {
|
|
23
|
-
throw new Error('[security] jobs.auth is required in production. Set jobs.auth or explicitly set unsafePublic: true with auth: "none".');
|
|
24
|
-
}
|
|
25
|
-
console.warn('[security] /jobs is enabled without auth. Configure jobs.auth for production.');
|
|
26
|
-
}
|
|
27
44
|
const { createJobsRouter } = await import(`${coreRoutesDir}/jobs`);
|
|
28
45
|
app.route('/', createJobsRouter(jobs, queueFactory));
|
|
29
46
|
}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"workspaces": [
|
|
4
4
|
"packages/*"
|
|
5
5
|
],
|
|
6
|
-
"version": "0.0
|
|
6
|
+
"version": "0.1.0",
|
|
7
7
|
"description": "Batteries-included Bun + Hono API framework — auth, sessions, rate limiting, WebSocket, queues, and OpenAPI docs out of the box",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
@@ -60,11 +60,15 @@
|
|
|
60
60
|
"topicSeparator": " "
|
|
61
61
|
},
|
|
62
62
|
"scripts": {
|
|
63
|
-
"typecheck": "bun --filter '*'
|
|
63
|
+
"typecheck": "bun run --filter '*' typecheck",
|
|
64
64
|
"typecheck:root": "tsc --noEmit",
|
|
65
65
|
"build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && tsup --config tsup.cli.config.ts && oclif manifest",
|
|
66
|
+
"build:packages": "bun run --filter '*' build",
|
|
66
67
|
"prepublishOnly": "bun run build",
|
|
67
|
-
"release": "
|
|
68
|
+
"release": "bun run build && bun publish --access public && bun run --filter '*' publish",
|
|
69
|
+
"release:patch": "bun run --filter '*' version patch && npm version patch && bun run release",
|
|
70
|
+
"release:minor": "bun run --filter '*' version minor && npm version minor && bun run release",
|
|
71
|
+
"release:major": "bun run --filter '*' version major && npm version major && bun run release",
|
|
68
72
|
"dev": "bun --watch src/index.ts",
|
|
69
73
|
"start": "bun src/index.ts",
|
|
70
74
|
"test": "bun test tests/unit tests/integration && bun run test:isolated && bun test --config packages/bunshot-core/bunfig.toml packages/bunshot-core/tests && bun test --config packages/bunshot-permissions/bunfig.toml packages/bunshot-permissions/tests",
|
|
@@ -92,8 +96,8 @@
|
|
|
92
96
|
"dependencies": {
|
|
93
97
|
"@asteasolutions/zod-to-openapi": "^8.4.1",
|
|
94
98
|
"@hono/zod-openapi": "1.2.2",
|
|
95
|
-
"@lastshotlabs/bunshot-auth": "
|
|
96
|
-
"@lastshotlabs/bunshot-core": "
|
|
99
|
+
"@lastshotlabs/bunshot-auth": "workspace:*",
|
|
100
|
+
"@lastshotlabs/bunshot-core": "workspace:*",
|
|
97
101
|
"@oclif/core": "^4.10.2",
|
|
98
102
|
"@scalar/hono-api-reference": "0.10.0",
|
|
99
103
|
"arctic": "^3.7.0",
|
|
@@ -110,7 +114,15 @@
|
|
|
110
114
|
"@simplewebauthn/server": ">=10.0.0",
|
|
111
115
|
"@aws-sdk/client-s3": ">=3.0",
|
|
112
116
|
"@aws-sdk/s3-request-presigner": ">=3.0",
|
|
113
|
-
"@aws-sdk/lib-storage": ">=3.0"
|
|
117
|
+
"@aws-sdk/lib-storage": ">=3.0",
|
|
118
|
+
"@lastshotlabs/bunshot-admin": ">=0.1.0",
|
|
119
|
+
"@lastshotlabs/bunshot-bullmq": ">=0.1.0",
|
|
120
|
+
"@lastshotlabs/bunshot-community": ">=0.1.0",
|
|
121
|
+
"@lastshotlabs/bunshot-mail": ">=0.0.1",
|
|
122
|
+
"@lastshotlabs/bunshot-permissions": ">=0.1.0",
|
|
123
|
+
"@lastshotlabs/bunshot-postgres": ">=0.1.0",
|
|
124
|
+
"@lastshotlabs/bunshot-push": ">=0.1.0",
|
|
125
|
+
"@lastshotlabs/bunshot-webhooks": ">=0.0.1"
|
|
114
126
|
},
|
|
115
127
|
"peerDependenciesMeta": {
|
|
116
128
|
"mongoose": {
|
|
@@ -136,9 +148,35 @@
|
|
|
136
148
|
},
|
|
137
149
|
"@aws-sdk/lib-storage": {
|
|
138
150
|
"optional": true
|
|
151
|
+
},
|
|
152
|
+
"@lastshotlabs/bunshot-admin": {
|
|
153
|
+
"optional": true
|
|
154
|
+
},
|
|
155
|
+
"@lastshotlabs/bunshot-bullmq": {
|
|
156
|
+
"optional": true
|
|
157
|
+
},
|
|
158
|
+
"@lastshotlabs/bunshot-community": {
|
|
159
|
+
"optional": true
|
|
160
|
+
},
|
|
161
|
+
"@lastshotlabs/bunshot-mail": {
|
|
162
|
+
"optional": true
|
|
163
|
+
},
|
|
164
|
+
"@lastshotlabs/bunshot-permissions": {
|
|
165
|
+
"optional": true
|
|
166
|
+
},
|
|
167
|
+
"@lastshotlabs/bunshot-postgres": {
|
|
168
|
+
"optional": true
|
|
169
|
+
},
|
|
170
|
+
"@lastshotlabs/bunshot-push": {
|
|
171
|
+
"optional": true
|
|
172
|
+
},
|
|
173
|
+
"@lastshotlabs/bunshot-webhooks": {
|
|
174
|
+
"optional": true
|
|
139
175
|
}
|
|
140
176
|
},
|
|
141
177
|
"devDependencies": {
|
|
178
|
+
"@aws-sdk/client-sesv2": "^3.1017.0",
|
|
179
|
+
"@react-email/render": "^2.0.4",
|
|
142
180
|
"@simplewebauthn/server": "^13.1.1",
|
|
143
181
|
"@trivago/prettier-plugin-sort-imports": "^6.0.2",
|
|
144
182
|
"@types/bun": "1.3.10",
|