Source Import Contracts¶
Source import is how the App Intelligence Plane acquires a local workspace root before indexing begins. It is a mandatory step before any source scan, tree-sitter extraction, framework detection, or graph build can happen.
Related documents:
Two Import Kinds¶
local_workspace¶
The source root is a directory already present on the machine running Studio. The resolver validates that the path exists and is a directory, then selects the workspace root (applying monorepo_path if provided).
Use this when Studio is running on the same machine as the app workspace. The two Studio HTTP indexing routes accept caller-supplied local paths only when authentication is explicitly disabled and the request has development access. Public visitors and authenticated Studio callers cannot submit a server filesystem path, even for an app they own: app ownership does not establish ownership of the source directory. Post-promotion indexing uses a server-derived workspace path through the internal helper and remains available. Authenticated brownfield imports need an owner-bound repository connector or another server-authorized source reference, rather than a path named by the HTTP caller. The OSS resolver currently rejects auth_connector_id, so private-repository import through this HTTP route is not yet implemented.
HTTP workflow launches without request-scoped development access reject caller-selected local discovery sources before dispatch. This applies to Studio's /api/workflows/trigger, the shared /api/transitions/resolve route, and runtime chat-start and programmatic workflow trigger routes. Guarded inputs include repo_path, split frontend/backend repository paths, and uploaded_openapi_path at the top level or inside discovery_inputs. Selecting host_app_source: workspace_app is blocked too because it resolves to the server's MOZAIKS_APP_WORKSPACE_PATH. Explicit no-auth local development may still use these inputs. Server-derived internal workflow context remains separate from the HTTP caller boundary.
git_repository¶
The resolver clones a remote repository to generated/source_imports/ before indexing. This supports the "import a public Git repo" flow in Studio.
The clone is: - shallow (--depth 1) for speed - scoped to a specific branch when branch is provided - placed at a deterministic path derived from app_id and the repo slug
After cloning, the commit_sha is captured and stored on the SourceImportResult for provenance.
OSS restriction: Only public HTTP(S) repositories are supported. URLs must not contain embedded credentials (username/password in netloc). Authenticated repository imports require a connector-backed credential resolver available only in hosted product deployments.
Request Schema¶
class SourceImportRequest(BaseModel):
source_kind: SourceImportKind = "local_workspace"
workspace_root: str | None # required for local_workspace
repo_url: str | None # required for git_repository; http(s) only
branch: str | None # optional; max 240 chars
monorepo_path: str | None # optional subpath within the workspace
auth_connector_id: str | None # always raises ValueError in OSS
ignored_paths: list[str] # merged into scan policy exclusions
Result Schema¶
class SourceImportResult(BaseModel):
source_kind: SourceImportKind
workspace_root: str # absolute path to the clone/local root
selected_root: str # workspace_root / monorepo_path (or workspace_root)
repo_url: str | None
branch: str | None
commit_sha: str | None # git_repository only
monorepo_path: str | None
ignored_paths: list[str]
warnings: list[str]
metadata: dict[str, Any]
selected_root is what the indexer actually scans. It equals workspace_root unless monorepo_path narrows it to a subdirectory.
Scan Policy Merging¶
source_import_scan_policy() merges ignored_paths from the import request into the canonical source scan policy override dict. The merged paths are deduplicated and stored as excluded_path_prefixes.
This is how Studio's "ignored paths" field on the import form reaches the scan step without duplicating scan policy logic in the Studio handler.
Security Model¶
Path containment¶
Both monorepo_path and the git clone directory are validated against their parent roots using Path.relative_to(). Any path that would escape the workspace root is rejected with ValueError before the filesystem is touched.
Containment alone does not authorize a caller to read a server directory. Studio's HTTP gate permits caller-provided local_workspace paths only when authentication was explicitly disabled and the request has development access. Keep that host local and trusted; the no-auth setting does not provide per-user filesystem access control. With AUTH_ANON_ACCESS=open, every client that can reach Studio receives development access and can submit a local path; bind that host to a trusted network boundary. The same restriction applies to caller-selected local source paths in ExistingAppDiscovery workflow launch and transition requests.
URL validation¶
For git_repository, the URL must: - use https:// or http:// scheme - have a non-empty netloc - have no username, password, or @ in netloc - have a non-empty path segment
No auth in OSS¶
auth_connector_id always raises ValueError in OSS. Private repository imports require a hosted product connector that supplies credentials at clone time.
Git command environment¶
Clone and commit lookup run with a limited process environment. Host service credentials and Git configuration overrides are not inherited; Git system and global configuration are disabled, parent repository lookup stops before each command's working-directory parent, and interactive credential prompts are disabled. The clone still has the host process's filesystem and network access.
Ignored path sanitization¶
safe_scan_relpath() is applied to every entry in ignored_paths before merging. Entries that escape the root, contain .., or are absolute paths are silently dropped.
Clone Directory and MOZAIKS_SOURCE_IMPORTS_PATH¶
Git clones are placed under a configurable root:
If the env var is unset, the path resolves relative to the repo root detected from __file__. Each app gets its own sub-directory:
An existing clone directory is removed and recreated on each import request. This ensures a fresh clone without requiring cleanup between runs.
Public Payload Redaction¶
public_source_import_result() strips the absolute workspace_root and selected_root from results surfaced through Studio's job API. The public payload reports workspace_root_present and selected_root_present as booleans instead.
The import_root key is also stripped from metadata. This prevents operator-specific filesystem layout from leaking into public job status payloads.
Relationship to App Intelligence Index Jobs¶
Studio creates an AppIntelligenceIndexJob record before calling the source import resolver. The resolved SourceImportResult is stored on the job as import_result (redacted for public views) and workspace_root.
The indexer reads workspace_root from the job when it starts the scan phase. If workspace_root is absent, it falls back to import_result.selected_root.
Implementation Map¶
| Concern | File |
|---|---|
| Request/result schemas | mozaiksai/control_plane/source_import.py — SourceImportRequest, SourceImportResult |
| Main resolver | mozaiksai/control_plane/source_import.py — resolve_source_import() |
| Scan policy merge | mozaiksai/control_plane/source_import.py — source_import_scan_policy() |
| Public payload redaction | mozaiksai/control_plane/source_import.py — public_source_import_result() |
| Path safety helper | mozaiksai/core/app_context/__init__.py — safe_scan_relpath() |
| Index job record | mozaiksai/control_plane/app_intelligence_jobs.py — AppIntelligenceIndexJob |
| Studio handler | mozaiksai/hosts/studio.py — source import and index endpoints |
| Tests | tests/test_source_import.py |
Contributor Rules¶
- Do not add provider-specific clone mechanics to OSS. Auth credential resolution belongs in the hosted product's connector layer.
- Do not allow
workspace_rootor absolute paths in public job payloads. Usepublic_source_import_result()before returning results to clients. - Path containment checks (
relative_to) must be applied to every operator-supplied path before any filesystem operation. ignored_pathsentries must always be sanitized throughsafe_scan_relpath()before merging into the scan policy.