Skip to content

Commit b90d15a

Browse files
committed
Merge branch 'main' into claude/update-metadata-service-dual-table-projection
2 parents fe3230d + 1584e50 commit b90d15a

10 files changed

Lines changed: 475 additions & 220 deletions

File tree

apps/studio/src/components/global-sidebar.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
ChevronsUpDown,
2929
Plus,
3030
Boxes,
31+
Globe,
3132
Package as PackageIcon,
3233
Settings,
3334
} from 'lucide-react';
@@ -179,6 +180,7 @@ export function GlobalSidebar() {
179180
const envsActive = pathname === '/environments';
180181
const packagesHref = envId ? `/environments/${envId}/packages` : undefined;
181182
const packagesActive = !!packagesHref && pathname === packagesHref;
183+
const apiConsoleActive = pathname === '/api-console';
182184

183185
return (
184186
<Sidebar collapsible="icon">
@@ -226,6 +228,17 @@ export function GlobalSidebar() {
226228
</SidebarMenuButton>
227229
)}
228230
</SidebarMenuItem>
231+
232+
{/* API Console — always available; the console discovers
233+
endpoints dynamically from the active client/environment. */}
234+
<SidebarMenuItem>
235+
<SidebarMenuButton asChild isActive={apiConsoleActive} tooltip="API Console">
236+
<Link to="/api-console">
237+
<Globe className="size-4" />
238+
<span>API Console</span>
239+
</Link>
240+
</SidebarMenuButton>
241+
</SidebarMenuItem>
229242
</SidebarMenu>
230243
</SidebarGroupContent>
231244
</SidebarGroup>

apps/studio/src/routes/__root.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ function isEnvExemptPath(pathname: string): boolean {
5252
pathname.startsWith('/login') ||
5353
pathname.startsWith('/register') ||
5454
pathname.startsWith('/orgs') ||
55-
pathname.startsWith('/environments')
55+
pathname.startsWith('/environments') ||
56+
pathname === '/api-console' ||
57+
pathname.startsWith('/api-console/')
5658
);
5759
}
5860

packages/metadata/src/objects/sys-metadata.object.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,24 @@ export const SysMetadataObject = ObjectSchema.create({
5555
maxLength: 100,
5656
}),
5757

58-
/** Package that owns/delivered this metadata */
58+
/** Package that owns/delivered this metadata (legacy string identifier, kept for compat) */
5959
package_id: Field.text({
6060
label: 'Package ID',
6161
required: false,
6262
maxLength: 255,
63+
description: 'Legacy package manifest ID string. Use package_version_id for new records.',
64+
}),
65+
66+
/**
67+
* FK → sys_package_version (UUID). Set for metadata that belongs to a specific
68+
* package release snapshot. NULL = platform-built-in or environment override.
69+
*/
70+
package_version_id: Field.text({
71+
label: 'Package Version ID',
72+
required: false,
73+
maxLength: 255,
74+
description:
75+
'Foreign key to sys_package_version (UUID). Null = platform-built-in or env-level override.',
6376
}),
6477

6578
/** Who manages this record: package, platform, or user */
@@ -184,6 +197,7 @@ export const SysMetadataObject = ObjectSchema.create({
184197
{ fields: ['type', 'scope'] },
185198
{ fields: ['organization_id'] },
186199
{ fields: ['env_id'] },
200+
{ fields: ['package_version_id'] },
187201
{ fields: ['state'] },
188202
{ fields: ['namespace'] },
189203
],

packages/objectos/CI_FIXES.md

Lines changed: 0 additions & 183 deletions
This file was deleted.

packages/services/service-tenant/src/objects/environment-objects.test.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import {
55
SysEnvironment,
66
SysDatabaseCredential,
77
SysEnvironmentMember,
8+
SysPackage,
9+
SysPackageVersion,
10+
SysPackageInstallation,
811
} from './index';
912

1013
describe('control-plane environment objects', () => {
@@ -51,3 +54,68 @@ describe('control-plane environment objects', () => {
5154
expect(SysEnvironmentMember.isSystem).toBe(true);
5255
});
5356
});
57+
58+
describe('control-plane package objects (ADR-0003)', () => {
59+
it('registers sys_package and sys_package_version with correct namespaced names', () => {
60+
expect(`${SysPackage.namespace}_${SysPackage.name}`).toBe('sys_package');
61+
expect(`${SysPackageVersion.namespace}_${SysPackageVersion.name}`).toBe('sys_package_version');
62+
expect(`${SysPackageInstallation.namespace}_${SysPackageInstallation.name}`).toBe('sys_package_installation');
63+
});
64+
65+
it('marks all package objects as system objects', () => {
66+
expect(SysPackage.isSystem).toBe(true);
67+
expect(SysPackageVersion.isSystem).toBe(true);
68+
expect(SysPackageInstallation.isSystem).toBe(true);
69+
});
70+
71+
it('sys_package has UNIQUE manifest_id index', () => {
72+
const idx = SysPackage.indexes ?? [];
73+
expect(
74+
idx.some((i: any) => i.unique && i.fields.join(',') === 'manifest_id'),
75+
).toBe(true);
76+
});
77+
78+
it('sys_package_version has UNIQUE (package_id, version) index', () => {
79+
const idx = SysPackageVersion.indexes ?? [];
80+
expect(
81+
idx.some((i: any) => i.unique && i.fields.join(',') === 'package_id,version'),
82+
).toBe(true);
83+
});
84+
85+
it('sys_package_installation has UNIQUE (environment_id, package_id) index', () => {
86+
const idx = SysPackageInstallation.indexes ?? [];
87+
expect(
88+
idx.some((i: any) => i.unique && i.fields.join(',') === 'environment_id,package_id'),
89+
).toBe(true);
90+
});
91+
92+
it('sys_package_installation has package_version_id field (not a version string)', () => {
93+
expect(SysPackageInstallation.fields).toHaveProperty('package_version_id');
94+
expect(SysPackageInstallation.fields).not.toHaveProperty('upgrade_history');
95+
});
96+
97+
it('sys_package_installation has package_version_id index', () => {
98+
const idx = SysPackageInstallation.indexes ?? [];
99+
expect(
100+
idx.some((i: any) => i.fields.join(',') === 'package_version_id'),
101+
).toBe(true);
102+
});
103+
104+
it('gives every field on sys_package a .description', () => {
105+
for (const [name, field] of Object.entries(SysPackage.fields)) {
106+
expect((field as any).description, `sys_package.${name} missing description`).toBeTruthy();
107+
}
108+
});
109+
110+
it('gives every field on sys_package_version a .description', () => {
111+
for (const [name, field] of Object.entries(SysPackageVersion.fields)) {
112+
expect((field as any).description, `sys_package_version.${name} missing description`).toBeTruthy();
113+
}
114+
});
115+
116+
it('gives every field on sys_package_installation a .description', () => {
117+
for (const [name, field] of Object.entries(SysPackageInstallation.fields)) {
118+
expect((field as any).description, `sys_package_installation.${name} missing description`).toBeTruthy();
119+
}
120+
});
121+
});

packages/services/service-tenant/src/objects/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export * from './sys-environment-member.object';
99
// docs/adr/0002-environment-database-isolation.md for the migration path.
1010
export * from './sys-tenant-database.object';
1111

12-
// Package installation registry (lives in control plane for now; will move
13-
// into each environment's data plane in v5.0 per ADR-0002).
12+
// Package registry (Control Plane, permanent — see ADR-0003).
13+
export * from './sys-package.object';
14+
export * from './sys-package-version.object';
1415
export * from './sys-package-installation.object';

0 commit comments

Comments
 (0)