@sequenceholdings/artifact-studio 0.6.7 → 0.7.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 (46) hide show
  1. package/README.md +26 -1
  2. package/dist/cli.js +4 -6
  3. package/dist/gateway/abort.d.ts +6 -0
  4. package/dist/gateway/abort.js +16 -0
  5. package/dist/gateway/authorization-cache.d.ts +24 -0
  6. package/dist/gateway/authorization-cache.js +21 -3
  7. package/dist/gateway/bootstrap-page.d.ts +16 -0
  8. package/dist/gateway/bootstrap-page.js +42 -0
  9. package/dist/gateway/control-config.d.ts +21 -0
  10. package/dist/gateway/control-config.js +18 -0
  11. package/dist/gateway/control.d.ts +61 -0
  12. package/dist/gateway/control.js +86 -7
  13. package/dist/gateway/hosted-proxy.d.ts +3 -0
  14. package/dist/gateway/hosted-proxy.js +12 -2
  15. package/dist/gateway/release-admission.d.ts +5 -0
  16. package/dist/gateway/release-admission.js +19 -0
  17. package/dist/gateway/server.d.ts +4 -1
  18. package/dist/gateway/server.js +35 -42
  19. package/dist/gateway/session.d.ts +9 -8
  20. package/dist/gateway/session.js +9 -11
  21. package/dist/gateway/static-files.d.ts +66 -0
  22. package/dist/gateway/static-files.js +112 -0
  23. package/dist/gateway/usage.d.ts +13 -0
  24. package/dist/gateway/usage.js +18 -0
  25. package/dist/gateway-main.js +8 -5
  26. package/dist/git-clone.d.ts +1 -3
  27. package/dist/git-clone.js +6 -8
  28. package/dist/manifest-next.d.ts +4 -0
  29. package/dist/manifest-static.d.ts +8 -0
  30. package/dist/manifest-static.js +5 -0
  31. package/dist/manifest.d.ts +8 -0
  32. package/dist/runtime-contracts.d.ts +8 -0
  33. package/dist/runtime-contracts.js +10 -0
  34. package/dist/sdk-orm.d.ts +3 -3
  35. package/dist/source-boundary.d.ts +6 -0
  36. package/dist/source-boundary.js +7 -2
  37. package/dist/source-resolver.js +7 -16
  38. package/dist/templates/nextjs/README.md +7 -0
  39. package/dist/templates/react-vite/package.json +5 -2
  40. package/dist/templates/react-vite/tsconfig.json +17 -0
  41. package/dist/trusted-install.d.ts +9 -2
  42. package/dist/trusted-install.js +9 -2
  43. package/package.json +4 -4
  44. package/templates/nextjs/README.md +7 -0
  45. package/templates/react-vite/package.json +5 -2
  46. package/templates/react-vite/tsconfig.json +17 -0
@@ -1,5 +1,13 @@
1
1
  import { z } from 'zod';
2
2
  export { resolveArtifactNextImages } from './next-image-config.js';
3
+ /** Atlas routes the gateway calls; every one authenticates the gateway itself. */
4
+ export declare const ARTIFACT_NEXT_CONTROL_PATH = "/api/artifact-studio/next/control";
5
+ /**
6
+ * The identity-token audience for gateway control calls: Atlas's public origin plus the control
7
+ * path, whichever address the call is routed to. Path-scoped, so a token minted for another
8
+ * Atlas audience is never accepted here.
9
+ */
10
+ export declare function artifactNextControlAudience(atlasOrigin: string): string;
3
11
  /** Shared by local collection, repository collection and the bounded source-upload API. */
4
12
  export declare const ARTIFACT_NEXT_SOURCE_LIMITS: Readonly<{
5
13
  maxFiles: 2000;
@@ -3,6 +3,16 @@ import { ARTIFACT_NEXT_RUNTIME, artifactNextSecretNameSchema } from './manifest-
3
3
  import { MAX_STUDIO_PATH_LENGTH } from './paths.js';
4
4
  import { isLoopbackHostname } from './loopback.js';
5
5
  export { resolveArtifactNextImages } from './next-image-config.js';
6
+ /** Atlas routes the gateway calls; every one authenticates the gateway itself. */
7
+ export const ARTIFACT_NEXT_CONTROL_PATH = '/api/artifact-studio/next/control';
8
+ /**
9
+ * The identity-token audience for gateway control calls: Atlas's public origin plus the control
10
+ * path, whichever address the call is routed to. Path-scoped, so a token minted for another
11
+ * Atlas audience is never accepted here.
12
+ */
13
+ export function artifactNextControlAudience(atlasOrigin) {
14
+ return `${new URL(atlasOrigin).origin}${ARTIFACT_NEXT_CONTROL_PATH}`;
15
+ }
6
16
  /** Shared by local collection, repository collection and the bounded source-upload API. */
7
17
  export const ARTIFACT_NEXT_SOURCE_LIMITS = Object.freeze({
8
18
  maxFiles: 2_000,
package/dist/sdk-orm.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { type OperationExecutor } from '@sequenceholdings/orm/client';
1
+ import { type SqlOperationExecutor } from '@sequenceholdings/orm/client';
2
2
  import { type ArtifactOrmJsonScalars } from './orm-json-scalars.js';
3
3
  import { type SequenceApi } from './sdk.js';
4
4
  export interface ArtifactOrmExecutorConfig {
5
5
  namespace: string;
6
6
  /** The generated operations.manifest.json, validated before any host call. */
7
- manifest: unknown;
7
+ manifest?: unknown;
8
8
  /** Optional action-scoped host client (for example, withTraceAction's client). */
9
9
  sdk?: {
10
10
  api: Pick<SequenceApi, 'fetch'>;
@@ -21,4 +21,4 @@ export interface ArtifactOrmExecutorConfig {
21
21
  * Declare the namespace path in capabilities.api.write (queries also use POST).
22
22
  * Namespace grants, capabilities, row policies, and write checks still apply.
23
23
  */
24
- export declare function createArtifactOrmExecutor({ namespace, manifest, sdk, jsonScalars }: ArtifactOrmExecutorConfig): OperationExecutor;
24
+ export declare function createArtifactOrmExecutor({ namespace, manifest, sdk, jsonScalars }: ArtifactOrmExecutorConfig): SqlOperationExecutor;
@@ -11,3 +11,9 @@ export interface ArtifactSourceBoundaryOptions {
11
11
  * allowed because they are external to the artifact by design.
12
12
  */
13
13
  export declare function rejectOutsideSourcePlugin({ root, trustedExternalRoots, }: ArtifactSourceBoundaryOptions): Plugin;
14
+ /**
15
+ * Whether `filePath` is inside a `node_modules` directory. Bundlers pass
16
+ * Windows paths with forward slashes, so compare in that form whatever the
17
+ * platform separator is.
18
+ */
19
+ export declare function isNodeModulesPath(filePath: string): boolean;
@@ -46,8 +46,13 @@ function isPathWithin(root, candidate) {
46
46
  function isTrustedExternalPath(filePath, trustedRoots) {
47
47
  return trustedRoots.some((trustedRoot) => isPathWithin(trustedRoot, filePath));
48
48
  }
49
- function isNodeModulesPath(filePath) {
50
- return filePath.includes(`${sep}node_modules${sep}`);
49
+ /**
50
+ * Whether `filePath` is inside a `node_modules` directory. Bundlers pass
51
+ * Windows paths with forward slashes, so compare in that form whatever the
52
+ * platform separator is.
53
+ */
54
+ export function isNodeModulesPath(filePath) {
55
+ return filePath.replaceAll('\\', '/').includes('/node_modules/');
51
56
  }
52
57
  function isBareImport(source) {
53
58
  return !source.startsWith('.') && !isAbsolute(source);
@@ -5,7 +5,7 @@ import { tmpdir } from 'node:os';
5
5
  import { isAbsolute, join, relative, resolve, sep } from 'node:path';
6
6
  import { createScrubbedChildEnv } from './child-environment.js';
7
7
  import { materializeRepo, resolveCommitSha, resolveRepo } from './git-service-client.js';
8
- import { gitServiceCloneUrl, resolveGitPatFromEnv, runGitClone } from './git-clone.js';
8
+ import { gitServiceCloneUrl, runGitClone } from './git-clone.js';
9
9
  /** True for sources that must be fetched from a remote (git-service / git-url). */
10
10
  export function isRemoteSpec(spec) {
11
11
  return spec.kind !== 'local';
@@ -136,21 +136,12 @@ export async function resolveArtifactSource(spec, opts = {}) {
136
136
  console.log(`[seq-studio] source: ${spec.namespace}/${spec.name}@${ref} (${sha.slice(0, 10)}, ${count} file(s), M2M)`);
137
137
  return await materialized({ gitCommit: sha, gitBranch: ref, gitDirty: false });
138
138
  }
139
- // Human path: materialize via a smart-HTTP `git clone` (one pack
140
- // transfer). The earlier per-blob JSON walk was O(files) serial HTTP
141
- // round-trips and stalled/failed on large artifacts. Smart-HTTP
142
- // authenticates by PAT (Basic-auth password), NOT the Auth0 bearer — the
143
- // same token you clone the repo with. No PAT, no git workflow.
144
- const pat = resolveGitPatFromEnv();
145
- if (pat) {
146
- const cloneUrl = gitServiceCloneUrl(opts.baseUrl, repo.id);
147
- await runGitClone({ cloneUrl, destDir: dest, pat, ref: sha });
148
- console.log(`[seq-studio] source: ${spec.namespace}/${spec.name}@${ref} (${sha.slice(0, 10)}, git clone)`);
149
- return await materialized({ gitCommit: sha, gitBranch: ref, gitDirty: false });
150
- }
151
- throw new Error('Deploying from --repo requires a git PAT. Set ATLAS_GIT_PAT to a token with the ' +
152
- 'repo:read scope (create one in Atlas → Settings → Tokens, or `seq-studio auth pat create`). ' +
153
- 'The git-service clone uses smart-HTTP, which authenticates by PAT — the same token you clone the repo with.');
139
+ // Use the same selected human identity for metadata and Git transport.
140
+ // An ambient PAT must not silently change the principal on the clone.
141
+ const cloneUrl = gitServiceCloneUrl(opts.baseUrl, repo.id);
142
+ await runGitClone({ cloneUrl, destDir: dest, pat: opts.token, ref: sha });
143
+ console.log(`[seq-studio] source: ${spec.namespace}/${spec.name}@${ref} (${sha.slice(0, 10)}, git clone)`);
144
+ return await materialized({ gitCommit: sha, gitBranch: ref, gitDirty: false });
154
145
  }
155
146
  const { sha, branch } = cloneGitUrl(spec.url, spec.ref, dest);
156
147
  console.log(`[seq-studio] source: ${redactGitUrl(spec.url)}${spec.ref ? `@${spec.ref}` : ''} (${sha.slice(0, 10)})`);
@@ -179,6 +179,13 @@ own test credentials, mocks or an existing governed function. Use a hosted
179
179
  preview for application code that needs a managed secret. Never put secrets in
180
180
  `build.public_env`, `NEXT_PUBLIC_*`, client components or committed files.
181
181
 
182
+ Cookies your application sets itself should use a `__Host-` name with `Secure`,
183
+ `HttpOnly`, `Path=/` and no `Domain`. Applications on one deployment share a
184
+ registrable domain, and only a `__Host-` cookie is guaranteed to come from your
185
+ own origin rather than a neighbour's. When the application origin is on a
186
+ different site from its Atlas frame, a cookie it needs there must also be
187
+ `SameSite=None; Partitioned`, or the browser drops it.
188
+
182
189
  The local process is ordinary code running as your operating-system user.
183
190
  Atlas governs access to platform resources; it does not sandbox your laptop's
184
191
  filesystem or all outbound network connections.
@@ -5,15 +5,18 @@
5
5
  "scripts": {
6
6
  "dev": "vite",
7
7
  "build": "vite build",
8
- "preview": "vite preview"
8
+ "preview": "vite preview",
9
+ "type-check": "tsc --noEmit"
9
10
  },
10
11
  "dependencies": {},
11
12
  "devDependencies": {
12
- "@sequenceholdings/artifact-studio": "^0.6.0",
13
+ "@sequenceholdings/artifact-studio": "^0.7.0",
13
14
  "@sequenceholdings/atlas-ui": "^3.1.1",
14
15
  "@tailwindcss/postcss": "^4.2.2",
15
16
  "@tailwindcss/vite": "^4.2.2",
16
17
  "@tanstack/react-query": "^4.36.1",
18
+ "@types/react": "^18.3.31",
19
+ "@types/react-dom": "^18.3.7",
17
20
  "@vitejs/plugin-react": "^5.0.0",
18
21
  "react": "^18.2.0",
19
22
  "react-dom": "^18.2.0",
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "skipLibCheck": true,
6
+ "strict": true,
7
+ "noEmit": true,
8
+ "esModuleInterop": true,
9
+ "module": "esnext",
10
+ "moduleResolution": "bundler",
11
+ "resolveJsonModule": true,
12
+ "isolatedModules": true,
13
+ "jsx": "react-jsx",
14
+ "types": ["vite/client"]
15
+ },
16
+ "include": ["src", "vite.config.ts"]
17
+ }
@@ -7,7 +7,14 @@ export declare const PNPM_WORKSPACE_FILE_RE: RegExp;
7
7
  /** Platform peers the CLI aliases at build time — must not be prod-installed remotely. */
8
8
  export declare const REMOTE_INSTALL_PLATFORM_PACKAGES: Set<string>;
9
9
  /**
10
- * Reject install-control files and non-registry dependency specs before a remote
11
- * `pnpm install` runs on an untrusted git checkout.
10
+ * Trust gate for remote static React/Vite artifact installs (called by
11
+ * `prepare-build.ts` before `pnpm install`); also reused for remote process repos.
12
+ * It rejects install-control files and non-registry dependency specs.
13
+ *
14
+ * Hosted Next.js builds use `prepareHostedBuildSource` in Atlas
15
+ * `next-hosted/source-policy.ts` and a controlled install workspace from
16
+ * `hostedInstallWorkspace` in `next-hosted/release-age.ts` instead. Do not apply
17
+ * this static gate to a Next.js template: its workspace file and approved
18
+ * platform dependencies follow the hosted policy.
12
19
  */
13
20
  export declare function assertTrustedArtifactInstallTree(dir: string): void;
@@ -225,8 +225,15 @@ function assertChainguardLockfile(dir) {
225
225
  assertParsedPackageResolutions(lockfileText);
226
226
  }
227
227
  /**
228
- * Reject install-control files and non-registry dependency specs before a remote
229
- * `pnpm install` runs on an untrusted git checkout.
228
+ * Trust gate for remote static React/Vite artifact installs (called by
229
+ * `prepare-build.ts` before `pnpm install`); also reused for remote process repos.
230
+ * It rejects install-control files and non-registry dependency specs.
231
+ *
232
+ * Hosted Next.js builds use `prepareHostedBuildSource` in Atlas
233
+ * `next-hosted/source-policy.ts` and a controlled install workspace from
234
+ * `hostedInstallWorkspace` in `next-hosted/release-age.ts` instead. Do not apply
235
+ * this static gate to a Next.js template: its workspace file and approved
236
+ * platform dependencies follow the hosted policy.
230
237
  */
231
238
  export function assertTrustedArtifactInstallTree(dir) {
232
239
  for (const rel of listRelativeFiles(dir)) {
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "publishConfig": {
10
10
  "access": "public"
11
11
  },
12
- "version": "0.6.7",
12
+ "version": "0.7.1",
13
13
  "description": "SDK types and CLI library for building Artifact Studio apps. Driven via `seq-studio artifact <sub>` (@sequenceholdings/studio-cli), which runs the `./cli` runCli export.",
14
14
  "type": "module",
15
15
  "exports": {
@@ -159,6 +159,7 @@
159
159
  "sonner": "^2.0.7",
160
160
  "tailwindcss": "^4.1.8",
161
161
  "tw-animate-css": "^1.4.0",
162
+ "typescript": "^5.6.0",
162
163
  "vite": "8.0.16",
163
164
  "zod": "^4.1.13",
164
165
  "ws": "^8.21.0",
@@ -166,14 +167,13 @@
166
167
  "google-auth-library": "^10.5.0",
167
168
  "server-only": "0.0.1",
168
169
  "parse5": "7.3.0",
170
+ "@sequenceholdings/lattice-form-renderer": "0.2.0",
169
171
  "@sequenceholdings/storage": "0.1.1",
170
- "@sequenceholdings/orm": "2.5.0",
171
- "@sequenceholdings/lattice-form-renderer": "0.2.0"
172
+ "@sequenceholdings/orm": "2.6.1"
172
173
  },
173
174
  "devDependencies": {
174
175
  "@types/js-yaml": "^4.0.9",
175
176
  "@types/node": "^22.0.0",
176
- "typescript": "^5.6.0",
177
177
  "vitest": "^4.1.11",
178
178
  "@types/ws": "^8.18.1"
179
179
  },
@@ -179,6 +179,13 @@ own test credentials, mocks or an existing governed function. Use a hosted
179
179
  preview for application code that needs a managed secret. Never put secrets in
180
180
  `build.public_env`, `NEXT_PUBLIC_*`, client components or committed files.
181
181
 
182
+ Cookies your application sets itself should use a `__Host-` name with `Secure`,
183
+ `HttpOnly`, `Path=/` and no `Domain`. Applications on one deployment share a
184
+ registrable domain, and only a `__Host-` cookie is guaranteed to come from your
185
+ own origin rather than a neighbour's. When the application origin is on a
186
+ different site from its Atlas frame, a cookie it needs there must also be
187
+ `SameSite=None; Partitioned`, or the browser drops it.
188
+
182
189
  The local process is ordinary code running as your operating-system user.
183
190
  Atlas governs access to platform resources; it does not sandbox your laptop's
184
191
  filesystem or all outbound network connections.
@@ -5,15 +5,18 @@
5
5
  "scripts": {
6
6
  "dev": "vite",
7
7
  "build": "vite build",
8
- "preview": "vite preview"
8
+ "preview": "vite preview",
9
+ "type-check": "tsc --noEmit"
9
10
  },
10
11
  "dependencies": {},
11
12
  "devDependencies": {
12
- "@sequenceholdings/artifact-studio": "^0.6.0",
13
+ "@sequenceholdings/artifact-studio": "^0.7.0",
13
14
  "@sequenceholdings/atlas-ui": "^3.1.1",
14
15
  "@tailwindcss/postcss": "^4.2.2",
15
16
  "@tailwindcss/vite": "^4.2.2",
16
17
  "@tanstack/react-query": "^4.36.1",
18
+ "@types/react": "^18.3.31",
19
+ "@types/react-dom": "^18.3.7",
17
20
  "@vitejs/plugin-react": "^5.0.0",
18
21
  "react": "^18.2.0",
19
22
  "react-dom": "^18.2.0",
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "skipLibCheck": true,
6
+ "strict": true,
7
+ "noEmit": true,
8
+ "esModuleInterop": true,
9
+ "module": "esnext",
10
+ "moduleResolution": "bundler",
11
+ "resolveJsonModule": true,
12
+ "isolatedModules": true,
13
+ "jsx": "react-jsx",
14
+ "types": ["vite/client"]
15
+ },
16
+ "include": ["src", "vite.config.ts"]
17
+ }