@push.rocks/smartregistry 1.1.1

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.
Files changed (52) hide show
  1. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  2. package/dist_ts/00_commitinfo_data.js +9 -0
  3. package/dist_ts/classes.smartregistry.d.ts +45 -0
  4. package/dist_ts/classes.smartregistry.js +113 -0
  5. package/dist_ts/core/classes.authmanager.d.ts +108 -0
  6. package/dist_ts/core/classes.authmanager.js +315 -0
  7. package/dist_ts/core/classes.baseregistry.d.ts +28 -0
  8. package/dist_ts/core/classes.baseregistry.js +6 -0
  9. package/dist_ts/core/classes.registrystorage.d.ts +109 -0
  10. package/dist_ts/core/classes.registrystorage.js +226 -0
  11. package/dist_ts/core/index.d.ts +7 -0
  12. package/dist_ts/core/index.js +10 -0
  13. package/dist_ts/core/interfaces.core.d.ts +142 -0
  14. package/dist_ts/core/interfaces.core.js +5 -0
  15. package/dist_ts/index.d.ts +8 -0
  16. package/dist_ts/index.js +13 -0
  17. package/dist_ts/npm/classes.npmregistry.d.ts +36 -0
  18. package/dist_ts/npm/classes.npmregistry.js +717 -0
  19. package/dist_ts/npm/index.d.ts +5 -0
  20. package/dist_ts/npm/index.js +6 -0
  21. package/dist_ts/npm/interfaces.npm.d.ts +245 -0
  22. package/dist_ts/npm/interfaces.npm.js +6 -0
  23. package/dist_ts/oci/classes.ociregistry.d.ts +43 -0
  24. package/dist_ts/oci/classes.ociregistry.js +565 -0
  25. package/dist_ts/oci/index.d.ts +5 -0
  26. package/dist_ts/oci/index.js +6 -0
  27. package/dist_ts/oci/interfaces.oci.d.ts +103 -0
  28. package/dist_ts/oci/interfaces.oci.js +5 -0
  29. package/dist_ts/paths.d.ts +1 -0
  30. package/dist_ts/paths.js +3 -0
  31. package/dist_ts/plugins.d.ts +6 -0
  32. package/dist_ts/plugins.js +9 -0
  33. package/npmextra.json +18 -0
  34. package/package.json +49 -0
  35. package/readme.hints.md +3 -0
  36. package/readme.md +486 -0
  37. package/ts/00_commitinfo_data.ts +8 -0
  38. package/ts/classes.smartregistry.ts +129 -0
  39. package/ts/core/classes.authmanager.ts +388 -0
  40. package/ts/core/classes.baseregistry.ts +36 -0
  41. package/ts/core/classes.registrystorage.ts +270 -0
  42. package/ts/core/index.ts +11 -0
  43. package/ts/core/interfaces.core.ts +159 -0
  44. package/ts/index.ts +16 -0
  45. package/ts/npm/classes.npmregistry.ts +890 -0
  46. package/ts/npm/index.ts +6 -0
  47. package/ts/npm/interfaces.npm.ts +263 -0
  48. package/ts/oci/classes.ociregistry.ts +734 -0
  49. package/ts/oci/index.ts +6 -0
  50. package/ts/oci/interfaces.oci.ts +101 -0
  51. package/ts/paths.ts +5 -0
  52. package/ts/plugins.ts +11 -0
@@ -0,0 +1,8 @@
1
+ /**
2
+ * autocreated commitinfo by @push.rocks/commitinfo
3
+ */
4
+ export declare const commitinfo: {
5
+ name: string;
6
+ version: string;
7
+ description: string;
8
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * autocreated commitinfo by @push.rocks/commitinfo
3
+ */
4
+ export const commitinfo = {
5
+ name: '@push.rocks/smartregistry',
6
+ version: '1.1.1',
7
+ description: 'a registry for npm modules and oci images'
8
+ };
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSwyQkFBMkI7SUFDakMsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLDJDQUEyQztDQUN6RCxDQUFBIn0=
@@ -0,0 +1,45 @@
1
+ import { RegistryStorage } from './core/classes.registrystorage.js';
2
+ import { AuthManager } from './core/classes.authmanager.js';
3
+ import { BaseRegistry } from './core/classes.baseregistry.js';
4
+ import type { IRegistryConfig, IRequestContext, IResponse } from './core/interfaces.core.js';
5
+ /**
6
+ * Main registry orchestrator
7
+ * Routes requests to appropriate protocol handlers (OCI or NPM)
8
+ */
9
+ export declare class SmartRegistry {
10
+ private storage;
11
+ private authManager;
12
+ private registries;
13
+ private config;
14
+ private initialized;
15
+ constructor(config: IRegistryConfig);
16
+ /**
17
+ * Initialize the registry system
18
+ */
19
+ init(): Promise<void>;
20
+ /**
21
+ * Handle an incoming HTTP request
22
+ * Routes to the appropriate protocol handler based on path
23
+ */
24
+ handleRequest(context: IRequestContext): Promise<IResponse>;
25
+ /**
26
+ * Get the storage instance (for testing/advanced use)
27
+ */
28
+ getStorage(): RegistryStorage;
29
+ /**
30
+ * Get the auth manager instance (for testing/advanced use)
31
+ */
32
+ getAuthManager(): AuthManager;
33
+ /**
34
+ * Get a specific registry handler
35
+ */
36
+ getRegistry(protocol: 'oci' | 'npm'): BaseRegistry | undefined;
37
+ /**
38
+ * Check if the registry is initialized
39
+ */
40
+ isInitialized(): boolean;
41
+ /**
42
+ * Clean up resources (timers, connections, etc.)
43
+ */
44
+ destroy(): void;
45
+ }
@@ -0,0 +1,113 @@
1
+ import { RegistryStorage } from './core/classes.registrystorage.js';
2
+ import { AuthManager } from './core/classes.authmanager.js';
3
+ import { BaseRegistry } from './core/classes.baseregistry.js';
4
+ import { OciRegistry } from './oci/classes.ociregistry.js';
5
+ import { NpmRegistry } from './npm/classes.npmregistry.js';
6
+ /**
7
+ * Main registry orchestrator
8
+ * Routes requests to appropriate protocol handlers (OCI or NPM)
9
+ */
10
+ export class SmartRegistry {
11
+ storage;
12
+ authManager;
13
+ registries = new Map();
14
+ config;
15
+ initialized = false;
16
+ constructor(config) {
17
+ this.config = config;
18
+ this.storage = new RegistryStorage(config.storage);
19
+ this.authManager = new AuthManager(config.auth);
20
+ }
21
+ /**
22
+ * Initialize the registry system
23
+ */
24
+ async init() {
25
+ if (this.initialized)
26
+ return;
27
+ // Initialize storage
28
+ await this.storage.init();
29
+ // Initialize auth manager
30
+ await this.authManager.init();
31
+ // Initialize OCI registry if enabled
32
+ if (this.config.oci?.enabled) {
33
+ const ociBasePath = this.config.oci.basePath || '/oci';
34
+ const ociRegistry = new OciRegistry(this.storage, this.authManager, ociBasePath);
35
+ await ociRegistry.init();
36
+ this.registries.set('oci', ociRegistry);
37
+ }
38
+ // Initialize NPM registry if enabled
39
+ if (this.config.npm?.enabled) {
40
+ const npmBasePath = this.config.npm.basePath || '/npm';
41
+ const registryUrl = `http://localhost:5000${npmBasePath}`; // TODO: Make configurable
42
+ const npmRegistry = new NpmRegistry(this.storage, this.authManager, npmBasePath, registryUrl);
43
+ await npmRegistry.init();
44
+ this.registries.set('npm', npmRegistry);
45
+ }
46
+ this.initialized = true;
47
+ }
48
+ /**
49
+ * Handle an incoming HTTP request
50
+ * Routes to the appropriate protocol handler based on path
51
+ */
52
+ async handleRequest(context) {
53
+ const path = context.path;
54
+ // Route to OCI registry
55
+ if (this.config.oci?.enabled && path.startsWith(this.config.oci.basePath)) {
56
+ const ociRegistry = this.registries.get('oci');
57
+ if (ociRegistry) {
58
+ return ociRegistry.handleRequest(context);
59
+ }
60
+ }
61
+ // Route to NPM registry
62
+ if (this.config.npm?.enabled && path.startsWith(this.config.npm.basePath)) {
63
+ const npmRegistry = this.registries.get('npm');
64
+ if (npmRegistry) {
65
+ return npmRegistry.handleRequest(context);
66
+ }
67
+ }
68
+ // No matching registry
69
+ return {
70
+ status: 404,
71
+ headers: { 'Content-Type': 'application/json' },
72
+ body: {
73
+ error: 'NOT_FOUND',
74
+ message: 'No registry handler for this path',
75
+ },
76
+ };
77
+ }
78
+ /**
79
+ * Get the storage instance (for testing/advanced use)
80
+ */
81
+ getStorage() {
82
+ return this.storage;
83
+ }
84
+ /**
85
+ * Get the auth manager instance (for testing/advanced use)
86
+ */
87
+ getAuthManager() {
88
+ return this.authManager;
89
+ }
90
+ /**
91
+ * Get a specific registry handler
92
+ */
93
+ getRegistry(protocol) {
94
+ return this.registries.get(protocol);
95
+ }
96
+ /**
97
+ * Check if the registry is initialized
98
+ */
99
+ isInitialized() {
100
+ return this.initialized;
101
+ }
102
+ /**
103
+ * Clean up resources (timers, connections, etc.)
104
+ */
105
+ destroy() {
106
+ for (const registry of this.registries.values()) {
107
+ if (typeof registry.destroy === 'function') {
108
+ registry.destroy();
109
+ }
110
+ }
111
+ }
112
+ }
113
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zbWFydHJlZ2lzdHJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5zbWFydHJlZ2lzdHJ5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUNwRSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDNUQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBRTlELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFFM0Q7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLGFBQWE7SUFDaEIsT0FBTyxDQUFrQjtJQUN6QixXQUFXLENBQWM7SUFDekIsVUFBVSxHQUE4QixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ2xELE1BQU0sQ0FBa0I7SUFDeEIsV0FBVyxHQUFZLEtBQUssQ0FBQztJQUVyQyxZQUFZLE1BQXVCO1FBQ2pDLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxlQUFlLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ25ELElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxXQUFXLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxJQUFJO1FBQ2YsSUFBSSxJQUFJLENBQUMsV0FBVztZQUFFLE9BQU87UUFFN0IscUJBQXFCO1FBQ3JCLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUUxQiwwQkFBMEI7UUFDMUIsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDO1FBRTlCLHFDQUFxQztRQUNyQyxJQUFJLElBQUks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
@@ -0,0 +1,108 @@
1
+ import type { IAuthConfig, IAuthToken, ICredentials, TRegistryProtocol } from './interfaces.core.js';
2
+ /**
3
+ * Unified authentication manager for all registry protocols
4
+ * Handles both NPM UUID tokens and OCI JWT tokens
5
+ */
6
+ export declare class AuthManager {
7
+ private config;
8
+ private tokenStore;
9
+ private userCredentials;
10
+ constructor(config: IAuthConfig);
11
+ /**
12
+ * Initialize the auth manager
13
+ */
14
+ init(): Promise<void>;
15
+ /**
16
+ * Create an NPM token
17
+ * @param userId - User ID
18
+ * @param readonly - Whether the token is readonly
19
+ * @returns NPM UUID token
20
+ */
21
+ createNpmToken(userId: string, readonly?: boolean): Promise<string>;
22
+ /**
23
+ * Validate an NPM token
24
+ * @param token - NPM UUID token
25
+ * @returns Auth token object or null
26
+ */
27
+ validateNpmToken(token: string): Promise<IAuthToken | null>;
28
+ /**
29
+ * Revoke an NPM token
30
+ * @param token - NPM UUID token
31
+ */
32
+ revokeNpmToken(token: string): Promise<void>;
33
+ /**
34
+ * List all tokens for a user
35
+ * @param userId - User ID
36
+ * @returns List of token info (without actual token values)
37
+ */
38
+ listUserTokens(userId: string): Promise<Array<{
39
+ key: string;
40
+ readonly: boolean;
41
+ created: string;
42
+ }>>;
43
+ /**
44
+ * Create an OCI JWT token
45
+ * @param userId - User ID
46
+ * @param scopes - Permission scopes
47
+ * @param expiresIn - Expiration time in seconds
48
+ * @returns JWT token string
49
+ */
50
+ createOciToken(userId: string, scopes: string[], expiresIn?: number): Promise<string>;
51
+ /**
52
+ * Validate an OCI JWT token
53
+ * @param jwt - JWT token string
54
+ * @returns Auth token object or null
55
+ */
56
+ validateOciToken(jwt: string): Promise<IAuthToken | null>;
57
+ /**
58
+ * Authenticate user credentials
59
+ * @param credentials - Username and password
60
+ * @returns User ID or null
61
+ */
62
+ authenticate(credentials: ICredentials): Promise<string | null>;
63
+ /**
64
+ * Validate any token (NPM or OCI)
65
+ * @param tokenString - Token string (UUID or JWT)
66
+ * @param protocol - Expected protocol type
67
+ * @returns Auth token object or null
68
+ */
69
+ validateToken(tokenString: string, protocol?: TRegistryProtocol): Promise<IAuthToken | null>;
70
+ /**
71
+ * Check if token has permission for an action
72
+ * @param token - Auth token
73
+ * @param resource - Resource being accessed (e.g., "package:foo" or "repository:bar")
74
+ * @param action - Action being performed (read, write, push, pull, delete)
75
+ * @returns true if authorized
76
+ */
77
+ authorize(token: IAuthToken | null, resource: string, action: string): Promise<boolean>;
78
+ /**
79
+ * Check if a scope matches a resource and action
80
+ * Scope format: "{protocol}:{type}:{name}:{action}"
81
+ * Examples:
82
+ * - "npm:*:*" - All NPM access
83
+ * - "npm:package:foo:*" - All actions on package foo
84
+ * - "npm:package:foo:read" - Read-only on package foo
85
+ * - "oci:repository:*:pull" - Pull from any OCI repo
86
+ */
87
+ private matchesScope;
88
+ /**
89
+ * Convert unified scopes to OCI access array
90
+ */
91
+ private scopesToOciAccess;
92
+ /**
93
+ * Convert OCI access array to unified scopes
94
+ */
95
+ private ociAccessToScopes;
96
+ /**
97
+ * Generate UUID for NPM tokens
98
+ */
99
+ private generateUuid;
100
+ /**
101
+ * Check if string is a valid UUID
102
+ */
103
+ private isValidUuid;
104
+ /**
105
+ * Hash a token for identification (SHA-512 mock)
106
+ */
107
+ private hashToken;
108
+ }
@@ -0,0 +1,315 @@
1
+ /**
2
+ * Unified authentication manager for all registry protocols
3
+ * Handles both NPM UUID tokens and OCI JWT tokens
4
+ */
5
+ export class AuthManager {
6
+ config;
7
+ tokenStore = new Map();
8
+ userCredentials = new Map(); // username -> password hash (mock)
9
+ constructor(config) {
10
+ this.config = config;
11
+ }
12
+ /**
13
+ * Initialize the auth manager
14
+ */
15
+ async init() {
16
+ // Initialize token store (in-memory for now)
17
+ // In production, this could be Redis or a database
18
+ }
19
+ // ========================================================================
20
+ // NPM AUTHENTICATION
21
+ // ========================================================================
22
+ /**
23
+ * Create an NPM token
24
+ * @param userId - User ID
25
+ * @param readonly - Whether the token is readonly
26
+ * @returns NPM UUID token
27
+ */
28
+ async createNpmToken(userId, readonly = false) {
29
+ if (!this.config.npmTokens.enabled) {
30
+ throw new Error('NPM tokens are not enabled');
31
+ }
32
+ const token = this.generateUuid();
33
+ const authToken = {
34
+ type: 'npm',
35
+ userId,
36
+ scopes: readonly ? ['npm:*:*:read'] : ['npm:*:*:*'],
37
+ readonly,
38
+ metadata: {
39
+ created: new Date().toISOString(),
40
+ },
41
+ };
42
+ this.tokenStore.set(token, authToken);
43
+ return token;
44
+ }
45
+ /**
46
+ * Validate an NPM token
47
+ * @param token - NPM UUID token
48
+ * @returns Auth token object or null
49
+ */
50
+ async validateNpmToken(token) {
51
+ if (!this.isValidUuid(token)) {
52
+ return null;
53
+ }
54
+ const authToken = this.tokenStore.get(token);
55
+ if (!authToken || authToken.type !== 'npm') {
56
+ return null;
57
+ }
58
+ // Check expiration if set
59
+ if (authToken.expiresAt && authToken.expiresAt < new Date()) {
60
+ this.tokenStore.delete(token);
61
+ return null;
62
+ }
63
+ return authToken;
64
+ }
65
+ /**
66
+ * Revoke an NPM token
67
+ * @param token - NPM UUID token
68
+ */
69
+ async revokeNpmToken(token) {
70
+ this.tokenStore.delete(token);
71
+ }
72
+ /**
73
+ * List all tokens for a user
74
+ * @param userId - User ID
75
+ * @returns List of token info (without actual token values)
76
+ */
77
+ async listUserTokens(userId) {
78
+ const tokens = [];
79
+ for (const [token, authToken] of this.tokenStore.entries()) {
80
+ if (authToken.userId === userId) {
81
+ tokens.push({
82
+ key: this.hashToken(token),
83
+ readonly: authToken.readonly || false,
84
+ created: authToken.metadata?.created || 'unknown',
85
+ });
86
+ }
87
+ }
88
+ return tokens;
89
+ }
90
+ // ========================================================================
91
+ // OCI AUTHENTICATION (JWT)
92
+ // ========================================================================
93
+ /**
94
+ * Create an OCI JWT token
95
+ * @param userId - User ID
96
+ * @param scopes - Permission scopes
97
+ * @param expiresIn - Expiration time in seconds
98
+ * @returns JWT token string
99
+ */
100
+ async createOciToken(userId, scopes, expiresIn = 3600) {
101
+ if (!this.config.ociTokens.enabled) {
102
+ throw new Error('OCI tokens are not enabled');
103
+ }
104
+ const now = Math.floor(Date.now() / 1000);
105
+ const payload = {
106
+ iss: this.config.ociTokens.realm,
107
+ sub: userId,
108
+ aud: this.config.ociTokens.service,
109
+ exp: now + expiresIn,
110
+ nbf: now,
111
+ iat: now,
112
+ access: this.scopesToOciAccess(scopes),
113
+ };
114
+ // In production, use proper JWT library with signing
115
+ // For now, return JSON string (mock JWT)
116
+ return JSON.stringify(payload);
117
+ }
118
+ /**
119
+ * Validate an OCI JWT token
120
+ * @param jwt - JWT token string
121
+ * @returns Auth token object or null
122
+ */
123
+ async validateOciToken(jwt) {
124
+ try {
125
+ // In production, verify JWT signature
126
+ const payload = JSON.parse(jwt);
127
+ // Check expiration
128
+ const now = Math.floor(Date.now() / 1000);
129
+ if (payload.exp && payload.exp < now) {
130
+ return null;
131
+ }
132
+ // Convert to unified token format
133
+ const scopes = this.ociAccessToScopes(payload.access || []);
134
+ return {
135
+ type: 'oci',
136
+ userId: payload.sub,
137
+ scopes,
138
+ expiresAt: payload.exp ? new Date(payload.exp * 1000) : undefined,
139
+ metadata: {
140
+ iss: payload.iss,
141
+ aud: payload.aud,
142
+ },
143
+ };
144
+ }
145
+ catch (error) {
146
+ return null;
147
+ }
148
+ }
149
+ // ========================================================================
150
+ // UNIFIED AUTHENTICATION
151
+ // ========================================================================
152
+ /**
153
+ * Authenticate user credentials
154
+ * @param credentials - Username and password
155
+ * @returns User ID or null
156
+ */
157
+ async authenticate(credentials) {
158
+ // Mock authentication - in production, verify against database
159
+ const storedPassword = this.userCredentials.get(credentials.username);
160
+ if (!storedPassword) {
161
+ // Auto-register for testing (remove in production)
162
+ this.userCredentials.set(credentials.username, credentials.password);
163
+ return credentials.username;
164
+ }
165
+ if (storedPassword === credentials.password) {
166
+ return credentials.username;
167
+ }
168
+ return null;
169
+ }
170
+ /**
171
+ * Validate any token (NPM or OCI)
172
+ * @param tokenString - Token string (UUID or JWT)
173
+ * @param protocol - Expected protocol type
174
+ * @returns Auth token object or null
175
+ */
176
+ async validateToken(tokenString, protocol) {
177
+ // Try NPM token first (UUID format)
178
+ if (this.isValidUuid(tokenString)) {
179
+ const npmToken = await this.validateNpmToken(tokenString);
180
+ if (npmToken && (!protocol || protocol === 'npm')) {
181
+ return npmToken;
182
+ }
183
+ }
184
+ // Try OCI JWT
185
+ const ociToken = await this.validateOciToken(tokenString);
186
+ if (ociToken && (!protocol || protocol === 'oci')) {
187
+ return ociToken;
188
+ }
189
+ return null;
190
+ }
191
+ /**
192
+ * Check if token has permission for an action
193
+ * @param token - Auth token
194
+ * @param resource - Resource being accessed (e.g., "package:foo" or "repository:bar")
195
+ * @param action - Action being performed (read, write, push, pull, delete)
196
+ * @returns true if authorized
197
+ */
198
+ async authorize(token, resource, action) {
199
+ if (!token) {
200
+ return false;
201
+ }
202
+ // Check readonly flag
203
+ if (token.readonly && ['write', 'push', 'delete'].includes(action)) {
204
+ return false;
205
+ }
206
+ // Check scopes
207
+ for (const scope of token.scopes) {
208
+ if (this.matchesScope(scope, resource, action)) {
209
+ return true;
210
+ }
211
+ }
212
+ return false;
213
+ }
214
+ // ========================================================================
215
+ // HELPER METHODS
216
+ // ========================================================================
217
+ /**
218
+ * Check if a scope matches a resource and action
219
+ * Scope format: "{protocol}:{type}:{name}:{action}"
220
+ * Examples:
221
+ * - "npm:*:*" - All NPM access
222
+ * - "npm:package:foo:*" - All actions on package foo
223
+ * - "npm:package:foo:read" - Read-only on package foo
224
+ * - "oci:repository:*:pull" - Pull from any OCI repo
225
+ */
226
+ matchesScope(scope, resource, action) {
227
+ const scopeParts = scope.split(':');
228
+ const resourceParts = resource.split(':');
229
+ // Scope must have at least protocol:type:name:action
230
+ if (scopeParts.length < 4) {
231
+ return false;
232
+ }
233
+ const [scopeProtocol, scopeType, scopeName, scopeAction] = scopeParts;
234
+ const [resourceProtocol, resourceType, resourceName] = resourceParts;
235
+ // Check protocol
236
+ if (scopeProtocol !== '*' && scopeProtocol !== resourceProtocol) {
237
+ return false;
238
+ }
239
+ // Check type
240
+ if (scopeType !== '*' && scopeType !== resourceType) {
241
+ return false;
242
+ }
243
+ // Check name
244
+ if (scopeName !== '*' && scopeName !== resourceName) {
245
+ return false;
246
+ }
247
+ // Check action
248
+ if (scopeAction !== '*' && scopeAction !== action) {
249
+ // Map action aliases
250
+ const actionAliases = {
251
+ read: ['pull', 'get'],
252
+ write: ['push', 'put', 'post'],
253
+ };
254
+ const aliases = actionAliases[scopeAction] || [];
255
+ if (!aliases.includes(action)) {
256
+ return false;
257
+ }
258
+ }
259
+ return true;
260
+ }
261
+ /**
262
+ * Convert unified scopes to OCI access array
263
+ */
264
+ scopesToOciAccess(scopes) {
265
+ const access = [];
266
+ for (const scope of scopes) {
267
+ const parts = scope.split(':');
268
+ if (parts.length >= 4 && parts[0] === 'oci') {
269
+ access.push({
270
+ type: parts[1],
271
+ name: parts[2],
272
+ actions: [parts[3]],
273
+ });
274
+ }
275
+ }
276
+ return access;
277
+ }
278
+ /**
279
+ * Convert OCI access array to unified scopes
280
+ */
281
+ ociAccessToScopes(access) {
282
+ const scopes = [];
283
+ for (const item of access) {
284
+ for (const action of item.actions) {
285
+ scopes.push(`oci:${item.type}:${item.name}:${action}`);
286
+ }
287
+ }
288
+ return scopes;
289
+ }
290
+ /**
291
+ * Generate UUID for NPM tokens
292
+ */
293
+ generateUuid() {
294
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
295
+ const r = (Math.random() * 16) | 0;
296
+ const v = c === 'x' ? r : (r & 0x3) | 0x8;
297
+ return v.toString(16);
298
+ });
299
+ }
300
+ /**
301
+ * Check if string is a valid UUID
302
+ */
303
+ isValidUuid(str) {
304
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
305
+ return uuidRegex.test(str);
306
+ }
307
+ /**
308
+ * Hash a token for identification (SHA-512 mock)
309
+ */
310
+ hashToken(token) {
311
+ // In production, use actual SHA-512
312
+ return `sha512-${token.substring(0, 16)}...`;
313
+ }
314
+ }
315
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5hdXRobWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2NvcmUvY2xhc3Nlcy5hdXRobWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQTs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sV0FBVztJQUlGO0lBSFosVUFBVSxHQUE0QixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ2hELGVBQWUsR0FBd0IsSUFBSSxHQUFHLEVBQUUsQ0FBQyxDQUFDLG1DQUFtQztJQUU3RixZQUFvQixNQUFtQjtRQUFuQixXQUFNLEdBQU4sTUFBTSxDQUFhO0lBQUcsQ0FBQztJQUUzQzs7T0FFRztJQUNJLEtBQUssQ0FBQyxJQUFJO1FBQ2YsNkNBQTZDO1FBQzdDLG1EQUFtRDtJQUNyRCxDQUFDO0lBRUQsMkVBQTJFO0lBQzNFLHFCQUFxQjtJQUNyQiwyRUFBMkU7SUFFM0U7Ozs7O09BS0c7SUFDSSxLQUFLLENBQUMsY0FBYyxDQUFDLE1BQWMsRUFBRSxXQUFvQixLQUFLO1FBQ25FLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNuQyxNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixDQUFDLENBQUM7UUFDaEQsQ0FBQztRQUVELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNsQyxNQUFNLFNBQVMsR0FBZTtZQUM1QixJQUFJLEVBQUUsS0FBSztZQUNYLE1BQU07WUFDTixNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQztZQUNuRCxRQUFRO1lBQ1IsUUFBUSxFQUFFO2dCQUNSLE9BQU8sRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRTthQUNsQztTQUNGLENBQUM7UUFFRixJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVB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
@@ -0,0 +1,28 @@
1
+ import type { IRequestContext, IResponse, IAuthToken } from './interfaces.core.js';
2
+ /**
3
+ * Abstract base class for all registry protocol implementations
4
+ */
5
+ export declare abstract class BaseRegistry {
6
+ /**
7
+ * Initialize the registry
8
+ */
9
+ abstract init(): Promise<void>;
10
+ /**
11
+ * Handle an incoming HTTP request
12
+ * @param context - Request context
13
+ * @returns Response object
14
+ */
15
+ abstract handleRequest(context: IRequestContext): Promise<IResponse>;
16
+ /**
17
+ * Get the base path for this registry protocol
18
+ */
19
+ abstract getBasePath(): string;
20
+ /**
21
+ * Validate that a token has the required permissions
22
+ * @param token - Authentication token
23
+ * @param resource - Resource being accessed
24
+ * @param action - Action being performed
25
+ * @returns true if authorized
26
+ */
27
+ protected abstract checkPermission(token: IAuthToken | null, resource: string, action: string): Promise<boolean>;
28
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Abstract base class for all registry protocol implementations
3
+ */
4
+ export class BaseRegistry {
5
+ }
6
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5iYXNlcmVnaXN0cnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9jb3JlL2NsYXNzZXMuYmFzZXJlZ2lzdHJ5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBOztHQUVHO0FBQ0gsTUFBTSxPQUFnQixZQUFZO0NBOEJqQyJ9