-
Notifications
You must be signed in to change notification settings - Fork 175
Stellar scafold fargate backend #646
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Stellar scafold fargate backend #646
Conversation
Co-authored-by: Eric Lau <[email protected]>
Reviewer's GuideThis PR scaffolds a new Rust-based Stellar backend API deployed via Fargate, integrates it with the existing Svelte UI for scaffold download, reorganizes the AI Deno server and import paths, and updates build/deploy configurations including Docker Compose and GitHub Actions workflows. Sequence diagram for Svelte UI downloading Stellar scaffold via Fargate backendsequenceDiagram
participant User as actor User
participant SvelteUI as Svelte UI
participant StellarAPI as Stellar Rust API (Fargate)
User->>SvelteUI: Click "Download Scaffold"
SvelteUI->>StellarAPI: POST /stellar/upgrade-scaffold (zip blob)
StellarAPI->>StellarAPI: Unzip, upgrade, re-zip contract
StellarAPI-->>SvelteUI: Return scaffold-project.zip
SvelteUI->>User: Save scaffold-project.zip
Class diagram for new and updated Rust backend modulesclassDiagram
class ServerConfig {
+host: String
+port: u16
+rate_limit_requests_per_second: u64
+wizard_origin: String
+from_environment_variables(): ServerConfig
}
class upgrade_scaffold {
+upgrade_to_scaffold(rust_contract_zip: web::Bytes): Result<Vec<u8>, HttpError>
}
class scaffold_upgrade {
+run_scaffold_upgrade_command(project_dir_path: &Path): Result<(), Error>
}
class zip_folder {
+unzip_in_temporary_folder(zip_data: Vec<u8>, expected_files: &[&str]): Result<TempDir, ZipError>
+zip_directory(zip_path: &Path): ZipResult<Vec<u8>>
}
class errors {
+to_http_hidden_error<E: Debug>(error: E): HttpError
+to_io_error<E: Debug>(error: E): IOError
+to_zip_io_error<E: Debug>(error: E): ZipError
}
ServerConfig <|-- upgrade_scaffold
upgrade_scaffold <|-- scaffold_upgrade
scaffold_upgrade <|-- zip_folder
zip_folder <|-- errors
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the 📝 WalkthroughWalkthroughAdds a new Rust-based Stellar API service (Actix-web) with secure ZIP handling and a scaffold upgrade endpoint, supporting Docker dev/prod builds and tests. Introduces staging/production GitHub Actions workflows with OIDC role chaining. Refactors AI API paths, adds editor/config ignores, environment samples, and UI changes to call the new scaffold upgrade flow. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant UI as UI (Stellar App.svelte)
participant RustAPI as Stellar API (Actix-web)
participant Env as Env Utils (ZIP & Scaffold)
note over UI: Build Rust project ZIP (zipRustProjectBlob)
User->>UI: Click "Scaffold Stellar Package"
UI->>RustAPI: POST /stellar/upgrade-scaffold (body: rust_project.zip)
alt Valid ZIP
RustAPI->>Env: unzip_in_temporary_folder(zip, expected_files)
Env-->>RustAPI: TempDir with files
RustAPI->>Env: run_scaffold_upgrade_command(temp_dir)
alt Upgrade OK
RustAPI->>Env: zip_directory(temp_dir)
Env-->>RustAPI: scaffold_project.zip
RustAPI-->>UI: 200 OK (application/zip)
UI->>User: Save scaffold-project.zip
else Upgrade fails
RustAPI-->>UI: 500 Internal Server Error
UI->>User: Show error state
end
else Invalid ZIP
RustAPI-->>UI: 415 Unsupported Media Type
UI->>User: Show error state
end
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120+ minutes Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@CoveMB the release workflows looks ok. I've left some comments. I will also need to provision the required resources to AWS e.g ECS cluster, ALB etc. I will do that work in a different IaC repository.
.github/workflows/docker-prod.yaml
Outdated
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 | ||
id: push | ||
with: | ||
context: . |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we don't have Dockerfile at the root, we need to specify a file
setting which points to the dockerfile. e.g
file: .//Dockerfile.production
.github/workflows/docker-prod.yaml
Outdated
fetch-depth: 0 | ||
|
||
- name: Prepare pre-requisites | ||
uses: ./.github/actions/prepare |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add this action. (the prepare
action)
No dependency changes detected. Learn more about Socket for GitHub. 👍 No dependency changes detected in pull request |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 20
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/ui/api/stellar/Dockerfile.prod (1)
1-66
: Prettier pipeline failing on Dockerfile; exclude it from formatting.Add the file to
.prettierignore
to unblock CI.Additional change outside this file:
+# .prettierignore +packages/ui/api/stellar/Dockerfile.prod
♻️ Duplicate comments (1)
.github/workflows/docker-prod.yaml (1)
65-77
: Specify the correct build context and Dockerfile; no root-level Dockerfile exists.This step will fail without
file:
or a correctedcontext
. Point it to the Stellar Dockerfile.Apply this diff:
- - name: Build Stellar API Docker image + - name: Build Stellar API Docker image (for scan) uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 id: build with: - context: . + context: packages/ui/api/stellar + file: Dockerfile.prod platforms: linux/amd64 # linux/arm64 causes anchore/scan-action to fail tags: | ${{ env.REGISTRY }}/wizard-stellar-api-prod:latest ${{ env.REGISTRY }}/wizard-stellar-api-prod:${{ github.sha }} cache-from: type=gha cache-to: type=gha,mode=max load: true
🧹 Nitpick comments (66)
.prettierignore (1)
18-19
: Confirm intent to skip formatting for .sh and .rs files
- Ignoring .rs is correct (rustfmt handles Rust).
- Ignoring .sh will disable any Prettier shell formatting (if a plugin exists). If you rely on shfmt instead, consider documenting it in CONTRIBUTING.md or adding a pre-commit hook.
.gitignore (1)
10-13
: Nit: debug/ may be redundantCargo places debug artifacts under target/, which is already ignored. Consider removing debug/ to avoid accidentally ignoring non-Cargo debug folders elsewhere.
# Generated by Cargo # will have compiled files and executables -debug/ target/
packages/ui/.env.example (1)
1-4
: Dotenv style nits and newline
- Drop quotes around ENV to satisfy common linters.
- Add a trailing newline.
-ENV="dev" +ENV=dev API_HOST=http://localhost:3000 FARGATE_HOST=http://localhost:8888 +packages/ui/api/ai/.env.example (1)
1-2
: Add trailing newlineTiny lint nit; add a newline at EOF.
API_PORT=3000 -OPENAI_API_KEY= +OPENAI_API_KEY= +packages/ui/api/ai/ai-assistant/function-definitions/shared.ts (2)
2-2
: Deep relative import is brittle; prefer import map aliasRecommend adding an alias (e.g., "common/") in packages/ui/api/ai/import_map.json and importing from 'common/src/ai/descriptions/common.ts' to avoid long ../../../ paths.
Example import_map.json entry (outside this diff):
{ "imports": { "common/": "../../../common/" } }Then:
import { commonDescriptions } from 'common/src/ai/descriptions/common.ts';
31-46
: Merge override order likely inverted; shared values currently override commonOptionsIf a key exists in both sharedFunctionDescription and commonOptions, the current spread makes shared win. Usually, caller-provided commonOptions should override defaults. Also, avoid rebuilding the merged object inside reduce.
) => - commonOptionNames.reduce( - (pickedCommonOptions, commonOptionName) => ({ - ...pickedCommonOptions, - [commonOptionName]: { ...commonOptions, ...sharedFunctionDescription }[commonOptionName], - }), - {} as Pick<typeof sharedFunctionDescription & TCommonOptions, TCommonOptionName>, - ); + { + const merged = { ...sharedFunctionDescription, ...commonOptions } as const; + return commonOptionNames.reduce( + (picked, name) => ({ + ...picked, + [name]: merged[name], + }), + {} as Pick<typeof merged, TCommonOptionName>, + ); + };.vscode/extensions.json (1)
5-7
: Fix trailing comma (invalid JSON).extensions.json is strict JSON; the trailing comma after the array breaks parsing.
Apply:
- "denoland.vscode-deno", - "rust-lang.rust-analyzer" - ], + "denoland.vscode-deno", + "rust-lang.rust-analyzer" + ]packages/ui/api/stellar/.env.example (1)
1-2
: Add trailing newline; consider documenting configurable port/host.
- Lint: file should end with a newline.
- Optional: if the server supports HOST/PORT vars, add them here for discoverability.
Can you confirm the exact env var names for host/port in packages/ui/api/stellar/src/config so we can include them?
packages/ui/api/stellar/rustfmt.toml (1)
2-5
: Remove unsupported rustfmt options; set edition in Cargo.toml.
- rustfmt reads edition from Cargo.toml, not rustfmt.toml.
- use_try_shorthand/use_field_init_shorthand are unstable or not honored in stable; they’ll be ignored and emit warnings.
Apply:
-max_width = 100 -tab_spaces = 4 -hard_tabs = false -edition = "2024" +max_width = 100 +tab_spaces = 4 +hard_tabs = false @@ -use_try_shorthand = true -use_field_init_shorthand = true +## Consider enabling only if you opt into nightly + unstable_features +# unstable_features = falseAnd in packages/ui/api/stellar/Cargo.toml set:
[package] edition = "2024" # if you’re actually on Rust 2024; otherwise "2021"
Also applies to: 17-19
.vscode/example.settings.json (1)
11-13
: Fix rust-analyzer linked project path (crate lives under api/stellar).Current path points to packages/ui/stellar, which doesn’t exist after the reorg.
Apply:
- "rust-analyzer.linkedProjects": [ - "packages/ui/stellar/Cargo.toml" - ], + "rust-analyzer.linkedProjects": [ + "packages/ui/api/stellar/Cargo.toml" + ],packages/ui/api/stellar/README.md (1)
1-1
: Fix heading indentation and make Docker build explicit.
- Remove leading spaces so headings lint cleanly.
- Use -f Dockerfile.prod to avoid ambiguity.
Apply:
- # Stellar Backend (Actix-web) +# Stellar Backend (Actix-web) @@ - ## Local Run +## Local Run @@ - ## Docker +## Docker @@ - docker build -t stellar packages/ui/api/stellar + docker build -f Dockerfile.prod -t stellar packages/ui/api/stellar docker run -p 8888:8888 stellarOptional: add a quick check tip:
curl -fsS http://localhost:8888/health
Also applies to: 5-5, 14-14, 16-19
packages/ui/src/cairo_alpha/App.svelte (1)
306-333
: Remove unused .controls-footer styles (silence Svelte warnings).CI warns these selectors are unused.
Apply:
- .controls-footer { - display: flex; - flex-direction: row; - justify-content: flex-end; - color: var(--gray-5); - margin-top: var(--size-3); - padding: 0 var(--size-2); - font-size: var(--text-small); - - & > * + * { - margin-left: var(--size-3); - } - - :global(.icon) { - margin-right: 0.2em; - opacity: 0.8; - } - - a { - color: inherit; - text-decoration: none; - - &:hover { - color: var(--text-color); - } - } - }packages/ui/api/stellar/Dockerfile.dev (1)
14-14
: Fix syntax error in package installation.Missing space between
gdb
and backslash continuation.- gdb\ + gdb \packages/ui/api/stellar/src/utils/glob.rs (3)
9-20
: Avoid intermediate Vec and generalize input; keep one pass build.Removes an allocation and broadens usability to any IntoIterator of AsRef.
-pub fn build_globset(patterns: Vec<String>) -> Result<GlobSet, GlobError> { - patterns - .iter() - .map(|p| Glob::new(p)) - .collect::<Result<Vec<_>, _>>()? - .into_iter() - .fold(GlobSetBuilder::new(), |mut builder, glob| { - builder.add(glob); - builder - }) - .build() -} +pub fn build_globset<I, S>(patterns: I) -> Result<GlobSet, GlobError> +where + I: IntoIterator<Item = S>, + S: AsRef<str>, +{ + patterns + .into_iter() + .try_fold(GlobSetBuilder::new(), |mut builder, p| { + let glob = Glob::new(p.as_ref())?; + builder.add(glob); + Ok::<_, GlobError>(builder) + })? + .build() +}
22-28
: Rename parameter for clarity: it's a candidate path, not a glob.Small readability win; avoids confusion with pattern vs input.
-pub fn is_glob_match(matchers: &GlobSet, glob: &str) -> Result<usize, MatchError> { - matchers - .matches(glob) +pub fn is_glob_match(matchers: &GlobSet, candidate: &str) -> Result<usize, MatchError> { + matchers + .matches(candidate) .first() .copied() - .ok_or_else(|| MatchError::NoMatch(glob.to_string())) + .ok_or_else(|| MatchError::NoMatch(candidate.to_string())) }
3-7
: Unused error variant; either wire it or drop it.
MatchError::Glob
isn’t produced anywhere. Consider addingimpl From<GlobError> for MatchError
or removing the variant until needed.+impl From<GlobError> for MatchError { + fn from(e: GlobError) -> Self { + MatchError::Glob(e) + } +}packages/ui/api/stellar/src/utils/path.rs (5)
6-20
: Preserve error kinds; don’t downgrade NotFound to Other.Keep semantics so callers can branch on kind.
- let can_path = canonicalize(dir).map_err(|e| { - if e.kind() == IoErrorKind::NotFound { - IoError::other("Directory does not exist") - } else { - e - } - })?; + let can_path = canonicalize(dir).map_err(|e| { + if e.kind() == IoErrorKind::NotFound { + IoError::new(IoErrorKind::NotFound, "directory does not exist") + } else { + e + } + })?; if !can_path.is_dir() { - return Err(IoError::other("destination is not a directory")); + return Err(IoError::new(IoErrorKind::InvalidInput, "destination is not a directory")); }
30-40
: Normalize separators for ancestors on all platforms.Without this, Windows ancestors may reintroduce backslashes and then you append “/”, producing mixed separators.
- .map(|a| a.components() - .filter(|c| !matches!(c, Component::CurDir)) - .collect::<std::path::PathBuf>() - .to_string_lossy() - .into_owned()) + .map(|a| { + let s = a + .components() + .filter(|c| !matches!(c, Component::CurDir)) + .collect::<PathBuf>() + .to_string_lossy() + .into_owned(); + norm(&s) + })
42-57
: Return order should be deterministic.Set iteration order is arbitrary; sort for stable results and flake‑free tests.
- set.into_iter().collect() + let mut out: Vec<_> = set.into_iter().collect(); + out.sort(); + out
67-97
: Use consistent error kinds and messages.Prefer
InvalidInput
overOther
for validation failures; keep messages consistent.let rel = path .strip_prefix(root) - .map_err(|_| IoError::other("path escapes root"))?; + .map_err(|_| IoError::new(IoErrorKind::InvalidInput, "path escapes root"))?; @@ let ft = symlink_metadata(&p)?.file_type(); if ft.is_symlink() { - Err(IoError::other("symlink detected")) + Err(IoError::new(IoErrorKind::InvalidInput, "symlink detected")) } else { Ok(()) } })?; @@ - Ok(meta) if meta.file_type().is_symlink() => { - return Err(IoError::other("symlink detected")) - } + Ok(meta) if meta.file_type().is_symlink() => { + return Err(IoError::new(IoErrorKind::InvalidInput, "symlink detected")) + }
30-40
: De-duplicate helpers across modules.There’s another
ancestors_rel
in environment/zip_folder.rs (PathBuf-based). Consider consolidating to one impl to avoid drift..github/actions/oidc/action.yaml (4)
33-33
: Clarify 900s session or make it configurable.You expose
role-duration-seconds
but fix step 1 to 900. Either document why, or parameterize with a separate input (e.g.,oidc-role-duration-seconds
).
38-41
: Prefer action outputs over env passthrough for chaining.Using
${{ steps.<id>.outputs.* }}
is clearer and avoids accidental env leakage.Example (no diff applied):
- Give step 1 an id (e.g.,
id: assume-oidc-role
).- Then:
aws-access-key-id: ${{ steps.assume-oidc-role.outputs.aws-access-key-id }}
etc.
45-45
: Add a trailing newline.Fixes YAML lint error.
- role-duration-seconds: ${{ inputs.role-duration-seconds }} + role-duration-seconds: ${{ inputs.role-duration-seconds }} +
24-45
: Pin is fine — latest release is v5.0.0 (2025-09-03), which is a major upgrade.
Keep the commit SHA pin; schedule periodic checks to auto-bump pins for new minor/patch releases, but require manual review and testing before upgrading to v5.x (major) due to possible breaking changes.packages/ui/api/stellar/tests/environment/zip_folder.rs (1)
1-1
: Empty test module; add at least one smoke test or remove placeholder.Prevents stale scaffolding; happy to draft tests against unzip/zip helpers.
packages/ui/api/ai/ai-assistant/function-definitions/stellar.ts (1)
102-106
: Duplicate property key: 'upgradeable' is defined twice in NonFungible; the latter overrides the spread.
Keep one source of truth to avoid drift.Apply:
sequential: { type: 'boolean', description: stellarNonFungibleDescriptions.sequential, }, - upgradeable: { - type: 'boolean', - description: stellarCommonDescriptions.upgradeable, - },packages/ui/src/solidity/App.svelte (1)
356-374
: Silence Svelte warnings by removing unused CSS selectors.
These selectors are flagged as unused in CI; safe to drop.Apply:
- .button-bg:hover { - transform: translateX(-2px); - transition: transform 300ms; - } - - .hide-deploy { - transform: translateX(-320px); - transition: transform 0.45s; - } - .hide-deploy button { - background-color: white; - border: 1px solid white; - } - - .hide-deploy:hover { - transform: translatex(-318px); - } + /* (removed unused .button-bg:hover and .hide-deploy styles) */- .controls-footer { - display: flex; - flex-direction: row; - justify-content: flex-end; - color: var(--gray-5); - margin-top: var(--size-3); - padding: 0 var(--size-2); - font-size: var(--text-small); - - & > * + * { - margin-left: var(--size-3); - } - - :global(.icon) { - margin-right: 0.2em; - opacity: 0.8; - } - - a { - color: inherit; - text-decoration: none; - - &:hover { - color: var(--text-color); - } - } - } + /* (removed unused .controls-footer block) */Also applies to: 457-483
packages/ui/src/stylus/App.svelte (1)
278-304
: Remove unused CSS selector for.controls-footer
and related styles.The pipeline failure indicates these CSS selectors are unused. Since this appears to be dead CSS code, it should be cleaned up.
Apply this diff to remove the unused CSS:
- .controls-footer { - display: flex; - flex-direction: row; - justify-content: flex-end; - color: var(--gray-5); - margin-top: var(--size-3); - padding: 0 var(--size-2); - font-size: var(--text-small); - - & > * + * { - margin-left: var(--size-3); - } - - :global(.icon) { - margin-right: 0.2em; - opacity: 0.8; - } - - a { - color: inherit; - text-decoration: none; - - &:hover { - color: var(--text-color); - } - } - }packages/ui/src/cairo/App.svelte (1)
300-326
: Remove unused CSS selector for.controls-footer
and related styles.The pipeline failure indicates these CSS selectors are unused. Since this appears to be dead CSS code, it should be cleaned up.
Apply this diff to remove the unused CSS:
- .controls-footer { - display: flex; - flex-direction: row; - justify-content: flex-end; - color: var(--gray-5); - margin-top: var(--size-3); - padding: 0 var(--size-2); - font-size: var(--text-small); - - & > * + * { - margin-left: var(--size-3); - } - - :global(.icon) { - margin-right: 0.2em; - opacity: 0.8; - } - - a { - color: inherit; - text-decoration: none; - - &:hover { - color: var(--text-color); - } - } - }packages/ui/api/stellar/src/environment/mod.rs (1)
1-4
: Tighten public surface: avoid glob re‑exports.Export only the intended symbols to prevent accidental API bloat and semver churn.
-mod zip_folder; -pub use zip_folder::*; -mod scaffold_upgrade; -pub use scaffold_upgrade::*; +//! Public environment utilities (keep exports minimal). +mod zip_folder; +pub use zip_folder::{ZipEntryLimits, unzip_in_temporary_folder, zip_directory, expected_entry_count}; +mod scaffold_upgrade; +pub use scaffold_upgrade::run_scaffold_upgrade_command;packages/ui/api/stellar/src/routes/health.rs (1)
1-14
: Add HEAD and no-store; be explicit on content type.Health endpoints are often cached by proxies; add Cache-Control: no-store and support HEAD.
-//! This module provides a health check endpoint for the API. -//! The `/health` endpoint can be used to verify that the service is running and responsive. -use actix_web::{get, web, HttpResponse}; +//! This module provides a health check endpoint for the API. +//! The `/health` endpoint can be used to verify that the service is running and responsive. +use actix_web::{get, head, http::header, web, HttpResponse}; -#[get("/health")] -async fn health() -> Result<HttpResponse, actix_web::Error> { - Ok(HttpResponse::Ok().body("OK")) -} +#[get("/health")] +async fn health() -> HttpResponse { + HttpResponse::Ok() + .insert_header((header::CACHE_CONTROL, "no-store")) + .insert_header((header::CONTENT_TYPE, "text/plain; charset=utf-8")) + .body("OK") +} + +#[head("/health")] +async fn health_head() -> HttpResponse { + HttpResponse::Ok() + .insert_header((header::CACHE_CONTROL, "no-store")) + .finish() +} /// Initializes the health check service. /// Registers the `health` endpoint with the provided service configuration. pub fn init(cfg: &mut web::ServiceConfig) { - cfg.service(health); + cfg.service(health).service(health_head); }packages/ui/api/stellar/src/config/mod.rs (1)
1-2
: Re-export only the needed types.Prefer explicit re-exports to keep the config surface stable.
-mod server; -pub use server::*; +//! Server configuration surface. +mod server; +pub use server::ServerConfig;packages/ui/api/stellar/src/controllers/mod.rs (1)
1-2
: Make controller re-exports explicit.Expose only the intended handler(s) to avoid leaking internals.
-mod upgrade_scaffold; -pub use upgrade_scaffold::*; +mod upgrade_scaffold; +pub use upgrade_scaffold::upgrade_to_scaffold;packages/ui/api/ai/ai-assistant/function-definitions/cairo-shared.ts (1)
3-7
: Use a tsconfig path alias for the common packageDeep relative imports are brittle — add a path alias and update the imports in packages/ui/api/ai/ai-assistant/function-definitions/cairo-shared.ts (lines ~3-7).
-import { infoDescriptions } from '../../../../../common/src/ai/descriptions/common.ts'; +import { infoDescriptions } from '@common/ai/descriptions/common.ts'; import { cairoCommonDescriptions, cairoRoyaltyInfoDescriptions, -} from '../../../../../common/src/ai/descriptions/cairo.ts'; +} from '@common/ai/descriptions/cairo.ts';Add to packages/ui/tsconfig.json:
{ "compilerOptions": { "baseUrl": ".", "paths": { "@common/*": ["../common/src/*"] } } }Verify no remaining deep imports:
rg -nP -S '\.\./\.\./\.\./\.\./\.\./common/src/ai/descriptions/(common|cairo)\.ts' packages -g '!**/dist/**'packages/ui/package.json (1)
10-11
: Prefer Docker Compose v2 CLI (or provide a fallback).Most environments expose Compose as
docker compose
(v2). Usingdocker-compose
can break dev flows.Apply this diff:
- "dev:api": "cd api && docker-compose up", - "dev:api:build": "cd api && docker-compose up --build", + "dev:api": "cd api && docker compose up", + "dev:api:build": "cd api && docker compose up --build",packages/ui/api/stellar/src/lib.rs (1)
9-11
: Doc grammar nit.“create, upgrading and zipping” → “creating, upgrading, and zipping”.
Apply this diff:
-//! * `environment` - The logic for create, upgrading and zipping the contract environment +//! * `environment` - The logic for creating, upgrading, and zipping the contract environmentpackages/ui/api/stellar/src/controllers/upgrade_scaffold.rs (4)
7-14
: Remove unused helper to avoid dead code warnings.
list_files
is not used and will trigger a warning in CI with-D warnings
.Apply this diff:
-fn list_files(dir: &Path) -> Vec<PathBuf> { - WalkDir::new(dir) - .into_iter() - .filter_map(|e| e.ok()) - .filter(|e| e.file_type().is_file()) - .map(|e| e.into_path()) - .collect() -}
16-25
: Hoist expected file patterns to a module-level constant.Avoids re-allocating on each call and clarifies intent.
Apply this diff:
-pub async fn upgrade_to_scaffold(rust_contract_zip: web::Bytes) -> Result<Vec<u8>, HttpError> { - let contract_zipped_files = [ +const CONTRACT_ZIPPED_FILES: &[&str] = &[ "contracts/*/src/contract.rs", "contracts/*/src/test.rs", "contracts/*/src/lib.rs", "contracts/*/Cargo.toml", "Cargo.toml", "README.md", - ]; +]; + +pub async fn upgrade_to_scaffold(rust_contract_zip: web::Bytes) -> Result<Vec<u8>, HttpError> {
26-31
: Don’t block Actix workers; offload the external CLI to a blocking thread.
run_scaffold_upgrade_command
is synchronous; running it on the worker can starve the server under load.Apply this diff:
- let contracts_dir = - unzip_in_temporary_folder(rust_contract_zip.to_vec(), &contract_zipped_files) + let contracts_dir = + unzip_in_temporary_folder(rust_contract_zip.to_vec(), CONTRACT_ZIPPED_FILES) .map_err(to_http_hidden_error)?; - run_scaffold_upgrade_command(contracts_dir.path()).map_err(to_http_hidden_error)?; + let project_dir = contracts_dir.path().to_path_buf(); + web::block(move || run_scaffold_upgrade_command(project_dir.as_path())) + .await + .map_err(to_http_hidden_error)? + .map_err(to_http_hidden_error)?;
32-35
: Zip work can be heavy; consider offloading as well.Zipping large trees can block a worker thread; offload similarly.
Apply this diff:
- let zipped_env = zip_directory(contracts_dir.path()).map_err(to_http_hidden_error)?; + let zip_root = contracts_dir.path().to_path_buf(); + let zipped_env = web::block(move || zip_directory(zip_root.as_path())) + .await + .map_err(to_http_hidden_error)? + .map_err(to_http_hidden_error)?;packages/ui/api/stellar/src/environment/scaffold_upgrade.rs (1)
7-25
: Consider adding a timeout and using async process APIs.A hung
stellar scaffold upgrade
would block indefinitely. Usingtokio::process
with a timeout improves resilience.If you choose to adopt this, we’ll also update the call site to
.await
the async function.-use std::{ - io::Error, - process::{Command, Stdio}, -}; +use std::io::Error; +use std::time::Duration; +use tokio::process::Command; +use tokio::time::timeout; -pub fn run_scaffold_upgrade_command(project_dir_path: &Path) -> Result<(), Error> { - let output = Command::new("stellar") +pub async fn run_scaffold_upgrade_command(project_dir_path: &Path) -> Result<(), Error> { + let child = Command::new("stellar") .args(["scaffold", "upgrade", "--skip-prompt"]) .stdin(Stdio::null()) .stdout(Stdio::null()) .stderr(Stdio::piped()) .current_dir(project_dir_path) - .output()?; + .output(); + + let output = timeout(Duration::from_secs(60), child) + .await + .map_err(|_| Error::other("Timed out running 'stellar scaffold upgrade'"))??; if output.status.success() { Ok(()) } else { Err(Error::other(format!( "'stellar scaffold upgrade' failed with code {:?}: {}", output.status.code(), String::from_utf8_lossy(&output.stderr) ))) } }.github/workflows/docker-prod.yaml (2)
131-133
: Add trailing newline.YAML lint flags “no newline at end of file”.
Apply this diff:
- aws ecs update-service --cluster $ECS_CLUSTER --service $ECS_SERVICE --force-new-deployment --region $AWS_REGION + aws ecs update-service --cluster $ECS_CLUSTER --service $ECS_SERVICE --force-new-deployment --region $AWS_REGION +
1-8
: Trigger on release is fine; consider tagging images with the release tag too.In addition to
latest
andsha
, pushing${{ github.event.release.tag_name }}
helps traceability.packages/ui/api/docker-compose.yaml (4)
6-8
: Use a dev Dockerfile for the dev service.You’re building the dev service with
Dockerfile.prod
. Switch back to.dev
as per TODO.Apply this diff:
- # TODO revert to .dev - dockerfile: Dockerfile.prod + dockerfile: Dockerfile.dev
31-34
: Mount common assets read-only to avoid accidental writes.Safer defaults for shared code/assets.
Apply this diff:
- - ../../common:/app/common + - ../../common:/app/common:ro
46-51
: Prune unused named volumes.
stellar-*
volumes are defined but not mounted; remove or comment until used.volumes: - stellar-cargo-target: - stellar-cargo-cache: - stellar-cargo-git: - stellar-tmp: deno-cache:
2-25
: Optional: add healthchecks for faster feedback.Healthchecks help
docker compose
report readiness for both services.I can draft healthcheck commands if you share the ports/paths (e.g.,
GET /health
for Stellar).packages/ui/api/stellar/src/routes/upgrade_scaffold.rs (1)
28-30
: Update init to register renamed handler.Apply:
pub fn init(cfg: &mut web::ServiceConfig) { - cfg.service(download_scaffold_route); + cfg.service(upgrade_scaffold_route); }packages/ui/api/stellar/src/utils/dir.rs (2)
7-17
: Tighten unix-only import usage and remove redundantuse DirBuilderExt;
.The local
use DirBuilderExt;
is unnecessary; fully qualify or rely on the gated import.Apply:
#[cfg(unix)] { - use DirBuilderExt; let mut b = DirBuilder::new(); b.recursive(true) .mode(0o700) .create(path) .map_err(to_io_error) }
24-49
: Good secure file creation; consider Windows hardening (optional).Unix path uses
O_NOFOLLOW
and 0600;ensure_no_symlinks
is also called pre-open. On Windows there’s noO_NOFOLLOW
; if this will run on Windows, consider an extrasymlink_metadata
check afteropen()
to ensure the created handle isn’t a reparse point..github/workflows/docker-stg.yaml (4)
1-3
: Header comment doesn’t match triggers.Comment says “whenever a release is created”, but the workflow triggers on pushes to
staging
and manual dispatch.Apply:
-# This workflow runs whenever a release is created. -# The image is tagged with latest and the release version. +# Builds, scans, and deploys on push to `staging` or manual dispatch.
49-54
: Validate OIDC role chaining early.Add a quick identity check to fail fast if role assumption breaks.
Apply:
- name: Set up AWS credentials via OIDC and role chaining uses: ./.github/actions/oidc with: role-for-oidc: ${{ env.ROLE_FOR_OIDC }} role-to-assume: ${{ env.ROLE_TO_ASSUME }} + - name: Verify AWS caller identity + run: aws sts get-caller-identity @@ - name: Set up AWS credentials via OIDC and role chaining uses: ./.github/actions/oidc with: role-for-oidc: ${{ env.ROLE_FOR_OIDC }} role-to-assume: ${{ env.ROLE_TO_ASSUME }} + - name: Verify AWS caller identity + run: aws sts get-caller-identityAlso applies to: 118-123
71-77
: Consider failing on high-severity vulns.Currently
fail-build: false
. Consider gating on high/critical severity.Example:
- fail-build: false + fail-build: true + severity-cutoff: high
126-126
: Add newline at end of file.YAML linter error: missing trailing newline.
packages/ui/api/stellar/src/config/server.rs (2)
20-23
: Docs vs code mismatch for APP_PORT default.Doc says 8080; code defaults to 8888. Make them consistent (pick one).
Apply either:
- Update docs to 8888:
- /// - `APP_PORT` defaults to `8080`. + /// - `APP_PORT` defaults to `8888`.
- Or change default to 8080:
- port: env::var("APP_PORT") - .unwrap_or_else(|_| "8888".to_string()) + port: env::var("APP_PORT") + .unwrap_or_else(|_| "8080".to_string()) .parse() - .unwrap_or(8888), + .unwrap_or(8080),Also applies to: 26-29
30-36
: Nit: clarify wizard_origin default in docs.Consider documenting the
WIZARD_ORIGIN
default alongside others for completeness.packages/ui/src/stellar/App.svelte (3)
37-38
: Guard missing FARGATE_HOST.Avoid an invalid URL like “undefined/stellar/…”.
-const fargateHost = process.env.FARGATE_HOST; +const fargateHost = process.env.FARGATE_HOST ?? '';
260-266
: Minor UX: ensure the progress text shows during retries.Because
downloadScaffoldError
isn’t cleared until success, users may still see the error message while a new attempt is in progress (since the error branch is checked first). The diff above clears it before starting.
309-309
: Clean up unused selectors to satisfy the pipeline.
.controls-footer
(and nested rules) are unused; remove or reintroduce the markup.packages/ui/api/stellar/src/environment/zip_folder.rs (2)
214-215
: Nit: typo in comment.“EvLUATE” -> “Evaluate”.
255-259
: Use 0644 for files; reserve 0755 for directories.Avoid making all files executable in the ZIP.
fn default_options() -> FileOptions<'static, ()> { - FileOptions::default() - .compression_method(CompressionMethod::Deflated) - .unix_permissions(0o755) + FileOptions::default() + .compression_method(CompressionMethod::Deflated) + .unix_permissions(0o644) }packages/core/stellar/src/zip-rust.ts (1)
60-64
: Unnecessary async/await nesting; simplify and avoid double-await.Make
zipRustProject
sync and callgenerateAsync
directly inzipRustProjectBlob
.-export const zipRustProject = async (c: Contract, opts: GenericOptions) => - addRustProjectReadme(createRustZipEnvironment(c, opts)); +export const zipRustProject = (c: Contract, opts: GenericOptions) => + addRustProjectReadme(createRustZipEnvironment(c, opts)); -export const zipRustProjectBlob = async (c: Contract, opts: GenericOptions) => - await (await zipRustProject(c, opts)).generateAsync({ type: 'blob', compression: 'DEFLATE' }); +export const zipRustProjectBlob = (c: Contract, opts: GenericOptions) => + zipRustProject(c, opts).generateAsync({ type: 'blob', compression: 'DEFLATE' });Optionally, maximize compression:
- ... { type: 'blob', compression: 'DEFLATE' }); + ... { type: 'blob', compression: 'DEFLATE', compressionOptions: { level: 9 } });packages/ui/api/stellar/Dockerfile.prod (2)
50-57
: Large runtime image and unnecessary toolchain in final image.Copying Cargo/Rustup homes bloats the image and increases attack surface. You already copy the needed binaries; drop the toolchains.
-ENV CARGO_HOME=/usr/local/cargo -ENV RUSTUP_HOME=/usr/local/rustup -ENV PATH=/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin -COPY --from=builder /usr/local/cargo/ $CARGO_HOME -COPY --from=builder /usr/local/rustup/ $RUSTUP_HOME - -RUN rm -rf /usr/local/cargo/registry /usr/local/cargo/git +ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binResult: smaller image, fewer CVE surfaces.
29-33
: Speed up builds with BuildKit caches for the target dir.Cache the target directory between builds.
-RUN TMPDIR=/opt/tmp cargo build --release +RUN --mount=type=cache,target=/opt/target,sharing=locked \ + TMPDIR=/opt/tmp cargo build --releasepackages/ui/api/ai/development-server.ts (1)
5-7
: Mixing two std path versions; import both from the same pinned module.Avoid split-version imports to prevent subtle incompatibilities.
-import { dirname } from 'https://deno.land/std/path/mod.ts'; -import { join } from 'https://deno.land/[email protected]/path/mod.ts'; +import { dirname, join } from 'https://deno.land/[email protected]/path/mod.ts';
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
packages/ui/api/ai/deno.lock
is excluded by!**/*.lock
packages/ui/api/stellar/Cargo.lock
is excluded by!**/*.lock
📒 Files selected for processing (68)
.github/actions/oidc/action.yaml
(1 hunks).github/workflows/docker-prod.yaml
(1 hunks).github/workflows/docker-stg.yaml
(1 hunks).gitignore
(1 hunks).prettierignore
(1 hunks).vscode/example.settings.json
(1 hunks).vscode/extensions.json
(1 hunks)netlify.toml
(1 hunks)package.json
(2 hunks)packages/core/stellar/src/zip-rust.ts
(1 hunks)packages/ui/.env.example
(1 hunks)packages/ui/api/ai/.env.example
(1 hunks)packages/ui/api/ai/Dockerfile.dev
(1 hunks)packages/ui/api/ai/ai-assistant/function-definitions/cairo-alpha-shared.ts
(1 hunks)packages/ui/api/ai/ai-assistant/function-definitions/cairo-alpha.ts
(1 hunks)packages/ui/api/ai/ai-assistant/function-definitions/cairo-shared.ts
(1 hunks)packages/ui/api/ai/ai-assistant/function-definitions/cairo.ts
(1 hunks)packages/ui/api/ai/ai-assistant/function-definitions/shared.ts
(1 hunks)packages/ui/api/ai/ai-assistant/function-definitions/solidity-shared.ts
(1 hunks)packages/ui/api/ai/ai-assistant/function-definitions/solidity.ts
(1 hunks)packages/ui/api/ai/ai-assistant/function-definitions/stellar-shared.ts
(1 hunks)packages/ui/api/ai/ai-assistant/function-definitions/stellar.ts
(1 hunks)packages/ui/api/ai/ai-assistant/function-definitions/stylus-shared.ts
(1 hunks)packages/ui/api/ai/ai-assistant/function-definitions/stylus.ts
(1 hunks)packages/ui/api/ai/ai-assistant/types/assistant.ts
(1 hunks)packages/ui/api/ai/deno.json
(1 hunks)packages/ui/api/ai/development-server.ts
(2 hunks)packages/ui/api/ai/paths/ai.ts
(1 hunks)packages/ui/api/docker-compose.yaml
(1 hunks)packages/ui/api/stellar/.dockerignore
(1 hunks)packages/ui/api/stellar/.env.example
(1 hunks)packages/ui/api/stellar/Cargo.toml
(1 hunks)packages/ui/api/stellar/Dockerfile.dev
(1 hunks)packages/ui/api/stellar/Dockerfile.prod
(1 hunks)packages/ui/api/stellar/README.md
(1 hunks)packages/ui/api/stellar/rustfmt.toml
(1 hunks)packages/ui/api/stellar/src/config/mod.rs
(1 hunks)packages/ui/api/stellar/src/config/server.rs
(1 hunks)packages/ui/api/stellar/src/controllers/mod.rs
(1 hunks)packages/ui/api/stellar/src/controllers/upgrade_scaffold.rs
(1 hunks)packages/ui/api/stellar/src/environment/mod.rs
(1 hunks)packages/ui/api/stellar/src/environment/scaffold_upgrade.rs
(1 hunks)packages/ui/api/stellar/src/environment/zip_folder.rs
(1 hunks)packages/ui/api/stellar/src/lib.rs
(1 hunks)packages/ui/api/stellar/src/main.rs
(1 hunks)packages/ui/api/stellar/src/routes/health.rs
(1 hunks)packages/ui/api/stellar/src/routes/mod.rs
(1 hunks)packages/ui/api/stellar/src/routes/upgrade_scaffold.rs
(1 hunks)packages/ui/api/stellar/src/utils/dir.rs
(1 hunks)packages/ui/api/stellar/src/utils/errors.rs
(1 hunks)packages/ui/api/stellar/src/utils/glob.rs
(1 hunks)packages/ui/api/stellar/src/utils/mod.rs
(1 hunks)packages/ui/api/stellar/src/utils/path.rs
(1 hunks)packages/ui/api/stellar/tests/environment/mod.rs
(1 hunks)packages/ui/api/stellar/tests/environment/zip_folder.rs
(1 hunks)packages/ui/api/stellar/tests/routes/health.rs
(1 hunks)packages/ui/api/stellar/tests/routes/mod.rs
(1 hunks)packages/ui/api/stellar/tests/tests_paths.rs
(1 hunks)packages/ui/api/stellar/tests/utils/glob.rs
(1 hunks)packages/ui/api/stellar/tests/utils/mod.rs
(1 hunks)packages/ui/package.json
(2 hunks)packages/ui/rollup.config.mjs
(1 hunks)packages/ui/src/cairo/App.svelte
(1 hunks)packages/ui/src/cairo_alpha/App.svelte
(1 hunks)packages/ui/src/common/Wiz.svelte
(1 hunks)packages/ui/src/solidity/App.svelte
(1 hunks)packages/ui/src/stellar/App.svelte
(3 hunks)packages/ui/src/stylus/App.svelte
(1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-08-19T15:21:06.991Z
Learnt from: ericglau
PR: OpenZeppelin/contracts-wizard#638
File: packages/core/cairo_alpha/src/account.test.ts.md:18-18
Timestamp: 2025-08-19T15:21:06.991Z
Learning: In the OpenZeppelin contracts-wizard repository, the cairo_alpha package (packages/core/cairo_alpha) and the stable cairo package (packages/core/cairo) are separate implementations that do not need to have the same code or matching dependency versions. The cairo_alpha package targets dependencies that are either newer than or the same as the stable cairo package, allowing it to test and support newer Cairo/Scarb/OpenZeppelin versions while the stable version maintains compatibility with stable releases.
Applied to files:
packages/ui/api/ai/ai-assistant/function-definitions/cairo.ts
packages/ui/api/ai/ai-assistant/function-definitions/cairo-alpha-shared.ts
packages/ui/api/ai/ai-assistant/function-definitions/cairo-alpha.ts
📚 Learning: 2025-08-19T15:31:24.984Z
Learnt from: ericglau
PR: OpenZeppelin/contracts-wizard#0
File: :0-0
Timestamp: 2025-08-19T15:31:24.984Z
Learning: Changes within packages/core/cairo_alpha should have a corresponding changelog entry in packages/core/cairo_alpha/CHANGELOG.md under the Unreleased section to track these changes. When cairo_alpha is eventually promoted to cairo (stable), these entries will be moved into a changeset for cairo (stable).
Applied to files:
packages/ui/api/ai/ai-assistant/function-definitions/cairo-alpha-shared.ts
packages/ui/api/ai/ai-assistant/function-definitions/cairo-alpha.ts
📚 Learning: 2025-08-19T15:18:09.410Z
Learnt from: ericglau
PR: OpenZeppelin/contracts-wizard#638
File: packages/core/cairo_alpha/src/scripts/update-scarb-project.ts:62-79
Timestamp: 2025-08-19T15:18:09.410Z
Learning: In the cairo_alpha package (packages/core/cairo_alpha), the OpenZeppelin dependency in test_project/Scarb.toml is expected to be in { git, tag } form rather than a simple registry-style string, so the update script only needs to update the tag value, not convert between formats.
Applied to files:
packages/ui/api/ai/ai-assistant/function-definitions/cairo-alpha.ts
🧬 Code graph analysis (12)
packages/ui/api/stellar/tests/utils/glob.rs (1)
packages/ui/api/stellar/src/utils/glob.rs (1)
build_globset
(9-20)
packages/ui/api/stellar/src/routes/health.rs (1)
packages/ui/api/stellar/src/routes/upgrade_scaffold.rs (1)
init
(28-30)
packages/ui/api/stellar/src/controllers/upgrade_scaffold.rs (3)
packages/ui/api/stellar/src/environment/scaffold_upgrade.rs (1)
run_scaffold_upgrade_command
(7-25)packages/ui/api/stellar/src/environment/zip_folder.rs (2)
unzip_in_temporary_folder
(18-35)zip_directory
(215-249)packages/ui/api/stellar/src/utils/errors.rs (1)
to_http_hidden_error
(7-10)
packages/ui/api/stellar/tests/routes/mod.rs (1)
packages/ui/api/stellar/src/routes/health.rs (1)
health
(6-8)
packages/ui/api/stellar/src/utils/dir.rs (2)
packages/ui/api/stellar/src/utils/path.rs (1)
ensure_no_symlinks
(67-99)packages/ui/api/stellar/src/utils/errors.rs (1)
to_io_error
(12-15)
packages/ui/api/stellar/src/utils/path.rs (1)
packages/ui/api/stellar/src/environment/zip_folder.rs (1)
ancestors_rel
(170-174)
packages/ui/api/stellar/src/routes/mod.rs (2)
packages/ui/api/stellar/src/routes/health.rs (2)
health
(6-8)init
(12-14)packages/ui/api/stellar/src/routes/upgrade_scaffold.rs (1)
init
(28-30)
packages/ui/api/stellar/src/routes/upgrade_scaffold.rs (2)
packages/ui/api/stellar/src/controllers/upgrade_scaffold.rs (1)
upgrade_to_scaffold
(16-36)packages/ui/api/stellar/src/routes/health.rs (1)
init
(12-14)
packages/ui/rollup.config.mjs (1)
packages/ui/svelte.config.js (1)
production
(3-3)
packages/ui/api/stellar/tests/routes/health.rs (1)
packages/ui/api/stellar/src/routes/health.rs (2)
health
(6-8)init
(12-14)
packages/ui/api/stellar/src/environment/zip_folder.rs (4)
packages/ui/api/stellar/src/utils/glob.rs (2)
build_globset
(9-20)is_glob_match
(22-28)packages/ui/api/stellar/src/utils/dir.rs (2)
create_dir_safe
(7-22)write_file_safe
(24-49)packages/ui/api/stellar/src/utils/path.rs (4)
expand_with_directories
(42-57)join_and_assert_inside
(59-65)ancestors_rel
(30-40)a
(35-37)packages/ui/api/stellar/src/utils/errors.rs (1)
to_zip_io_error
(17-20)
packages/ui/api/stellar/src/main.rs (4)
packages/ui/api/stellar/src/routes/mod.rs (1)
configure_routes
(6-9)packages/ui/api/stellar/src/routes/upgrade_scaffold.rs (1)
init
(28-30)packages/ui/api/stellar/src/routes/health.rs (1)
init
(12-14)packages/ui/api/stellar/src/config/server.rs (1)
from_environment_variables
(23-37)
🪛 GitHub Actions: Test
packages/ui/src/cairo_alpha/App.svelte
[warning] 226-226: Unused CSS selector ".controls-footer" (svelte)
[warning] 226-226: Unused CSS selector ".controls-footer > * + *" (svelte)
[warning] 226-226: Unused CSS selector ".controls-footer :global(.icon)" (svelte)
[warning] 226-226: Unused CSS selector ".controls-footer a" (svelte)
[warning] 226-226: Unused CSS selector ".controls-footer a:hover" (svelte)
packages/ui/src/cairo/App.svelte
[warning] 220-220: Unused CSS selector ".controls-footer" (svelte)
[warning] 220-220: Unused CSS selector ".controls-footer > * + *" (svelte)
[warning] 220-220: Unused CSS selector ".controls-footer :global(.icon)" (svelte)
[warning] 220-220: Unused CSS selector ".controls-footer a" (svelte)
[warning] 220-220: Unused CSS selector ".controls-footer a:hover" (svelte)
packages/ui/src/stylus/App.svelte
[warning] 198-198: Unused CSS selector ".controls-footer" (svelte)
[warning] 198-198: Unused CSS selector ".controls-footer > * + *" (svelte)
[warning] 198-198: Unused CSS selector ".controls-footer :global(.icon)" (svelte)
[warning] 198-198: Unused CSS selector ".controls-footer a" (svelte)
[warning] 198-198: Unused CSS selector ".controls-footer a:hover" (svelte)
packages/ui/src/solidity/App.svelte
[warning] 356-356: Unused CSS selector ".button-bg:hover" (svelte)
[warning] 356-356: Unused CSS selector ".hide-deploy" (svelte)
[warning] 356-356: Unused CSS selector ".hide-deploy button" (svelte)
[warning] 356-356: Unused CSS selector ".hide-deploy:hover" (svelte)
[warning] 356-356: Unused CSS selector ".controls-footer" (svelte)
[warning] 356-356: Unused CSS selector ".controls-footer > * + *" (svelte)
[warning] 356-356: Unused CSS selector ".controls-footer :global(.icon)" (svelte)
[warning] 356-356: Unused CSS selector ".controls-footer a" (svelte)
[warning] 356-356: Unused CSS selector ".controls-footer a:hover" (svelte)
packages/ui/api/ai/Dockerfile.dev
[error] 1-1: Prettier: No parser could be inferred for file /home/runner/work/contracts-wizard/contracts-wizard/packages/ui/api/ai/Dockerfile.dev.
packages/ui/api/stellar/Dockerfile.dev
[error] 1-1: Prettier: No parser could be inferred for file /home/runner/work/contracts-wizard/contracts-wizard/packages/ui/api/stellar/Dockerfile.dev.
packages/ui/api/stellar/Dockerfile.prod
[error] 1-1: Prettier: No parser could be inferred for file /home/runner/work/contracts-wizard/contracts-wizard/packages/ui/api/stellar/Dockerfile.prod.
packages/ui/src/stellar/App.svelte
[warning] 309-309: Unused CSS selector ".controls-footer" (svelte)
[warning] 309-309: Unused CSS selector ".controls-footer > * + *" (svelte)
[warning] 309-309: Unused CSS selector ".controls-footer :global(.icon)" (svelte)
[warning] 309-309: Unused CSS selector ".controls-footer a" (svelte)
[warning] 309-309: Unused CSS selector ".controls-footer a:hover" (svelte)
🪛 actionlint (1.7.7)
.github/workflows/docker-prod.yaml
44-44: description is required in metadata of "Setup" action at "/home/jailuser/git/.github/actions/setup/action.yml"
(action)
46-46: input "token" is not defined in action "Setup" defined at "./.github/actions/setup". available inputs are
(action)
🪛 YAMLlint (1.37.1)
.github/workflows/docker-prod.yaml
[error] 133-133: no new line character at the end of file
(new-line-at-end-of-file)
.github/workflows/docker-stg.yaml
[error] 126-126: no new line character at the end of file
(new-line-at-end-of-file)
.github/actions/oidc/action.yaml
[error] 45-45: no new line character at the end of file
(new-line-at-end-of-file)
🪛 dotenv-linter (3.3.0)
packages/ui/.env.example
[warning] 1-1: [QuoteCharacter] The value has quote characters (', ")
(QuoteCharacter)
[warning] 4-4: [EndingBlankLine] No blank line at the end of the file
(EndingBlankLine)
packages/ui/api/stellar/.env.example
[warning] 2-2: [EndingBlankLine] No blank line at the end of the file
(EndingBlankLine)
packages/ui/api/ai/.env.example
[warning] 2-2: [EndingBlankLine] No blank line at the end of the file
(EndingBlankLine)
🪛 markdownlint-cli2 (0.17.2)
packages/ui/api/stellar/README.md
1-1: Headings must start at the beginning of the line
(MD023, heading-start-left)
5-5: Headings must start at the beginning of the line
(MD023, heading-start-left)
14-14: Headings must start at the beginning of the line
(MD023, heading-start-left)
- name: assume oidc role | ||
uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0 | ||
with: | ||
aws-region: us-east-1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don’t hard‑code AWS region; respect the input.
This breaks callers outside us‑east‑1.
- aws-region: us-east-1
+ aws-region: ${{ inputs.aws-region }}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
aws-region: us-east-1 | |
aws-region: ${{ inputs.aws-region }} |
🤖 Prompt for AI Agents
.github/actions/oidc/action.yaml around line 30: the aws-region is hard-coded to
"us-east-1" which ignores caller input; update the action to use the aws-region
input variable (falling back to a sensible default only if input is empty) so
callers can supply their region, and remove the fixed "us-east-1" literal.
- name: Setup pre-requisites | ||
uses: ./.github/actions/setup | ||
with: | ||
token: ${{ steps.gh-app-token.outputs.token }} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Local action input mismatch (actionlint): setup
action lacks a token
input and description.
Per static analysis, ./.github/actions/setup
doesn’t define inputs.token
and is missing description
. This step will error.
Options:
- Define
inputs.token
anddescription
in./.github/actions/setup/action.yml
, or - Remove the
with: token: ...
from this step if unused.
🧰 Tools
🪛 actionlint (1.7.7)
44-44: description is required in metadata of "Setup" action at "/home/jailuser/git/.github/actions/setup/action.yml"
(action)
46-46: input "token" is not defined in action "Setup" defined at "./.github/actions/setup". available inputs are
(action)
🤖 Prompt for AI Agents
In .github/workflows/docker-prod.yaml around lines 43 to 47, the workflow step
calls the local action ./.github/actions/setup with a `with: token: ...` but
that action's action.yml lacks an `inputs.token` entry and a `description`,
causing actionlint errors; fix by editing .github/actions/setup/action.yml to
add a descriptive `description` field and declare an `inputs` mapping that
includes `token` (type string, required if used, with a short description and
default if appropriate) so the workflow input is valid, or alternatively remove
the `with: token: ${{ steps.gh-app-token.outputs.token }}` line from the
workflow if the action does not need the token.
inputs: | ||
branch: | ||
description: 'Branch to build from' | ||
required: true | ||
default: 'ci-cd' | ||
type: string | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
workflow_dispatch
input branch
is unused. Wire it to checkout.
Use actions/checkout@…
with ref: ${{ inputs.branch }}
when manually dispatched.
Apply:
workflow_dispatch:
inputs:
branch:
description: 'Branch to build from'
required: true
- default: 'ci-cd'
+ default: 'staging'
type: string
@@
- - name: Checkout code
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - name: Checkout code
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ ref: ${{ github.event_name == 'workflow_dispatch' && inputs.branch || github.ref }}
Also applies to: 38-40
🤖 Prompt for AI Agents
In .github/workflows/docker-stg.yaml around lines 9-15 (and similarly update
lines 38-40), the workflow_dispatch input "branch" is declared but never used;
update the checkout step(s) to pass that input by setting actions/checkout@...
with ref: ${{ inputs.branch }} so the workflow checks out the specified branch
when manually dispatched; ensure you add the ref field to every actions/checkout
step that should honor the input.
export const ChatRoles = ['user', 'assistant', 'system']; | ||
export type Chat = { | ||
role: 'user' | 'assistant' | 'system'; | ||
role: (typeof ChatRoles)[number]; | ||
content: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make ChatRoles a literal tuple to preserve role type safety.
Without as const, (typeof ChatRoles)[number] collapses to string.
Apply:
-export const ChatRoles = ['user', 'assistant', 'system'];
+export const ChatRoles = ['user', 'assistant', 'system'] as const;
export type Chat = {
- role: (typeof ChatRoles)[number];
+ role: (typeof ChatRoles)[number];
content: string;
};
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
export const ChatRoles = ['user', 'assistant', 'system']; | |
export type Chat = { | |
role: 'user' | 'assistant' | 'system'; | |
role: (typeof ChatRoles)[number]; | |
content: string; | |
export const ChatRoles = ['user', 'assistant', 'system'] as const; | |
export type Chat = { | |
role: (typeof ChatRoles)[number]; | |
content: string; | |
}; |
🤖 Prompt for AI Agents
In packages/ui/api/ai/ai-assistant/types/assistant.ts around lines 9 to 12,
ChatRoles is defined as a mutable string array which causes (typeof
ChatRoles)[number] to widen to string; change ChatRoles to a readonly literal
tuple by appending "as const" (e.g. export const ChatRoles =
['user','assistant','system'] as const) so the role type remains the exact union
of those strings, and optionally introduce a ChatRole type alias (export type
ChatRole = typeof ChatRoles[number]) and use that for the Chat.role declaration.
const listAll = async (dirPath: string) => { | ||
for await (const entry of Deno.readDir(dirPath)) { | ||
const fullPath = join(dirPath, entry.name); | ||
console.log(fullPath); | ||
|
||
if (entry.isDirectory) { | ||
await listAll(fullPath); | ||
} | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove recursive directory logging on every request.
listAll('.')
on each request is noisy, slow, and leaks filesystem layout in logs.
-const listAll = async (dirPath: string) => {
- for await (const entry of Deno.readDir(dirPath)) {
- const fullPath = join(dirPath, entry.name);
- console.log(fullPath);
-
- if (entry.isDirectory) {
- await listAll(fullPath);
- }
- }
-};
+// Optional debug-only scanner (disabled by default)
+const listAll = async (_: string) => {};
Also applies to: 38-39
🤖 Prompt for AI Agents
In packages/ui/api/ai/development-server.ts around lines 8-17 (and also
addressing the call at lines 38-39), the recursive helper listAll('.') currently
logs every file path on each request, which is noisy, slow, and leaks filesystem
layout; remove the recursive listing and any console.log calls or gate them
behind a strict debug flag so they never run on normal requests. Specifically,
delete or disable the listAll('.') invocation at lines 38-39 and remove the
console.log(fullPath) from the helper (or eliminate the helper entirely if
unused), and if you need optional diagnostics, expose a debug option that
triggers a single, non-recursive, rate-limited or explicitly-invoked listing
instead of running it per request.
#[cfg(not(unix))] | ||
{ | ||
fs::create_dir_all(path).map_err(utils::to_io_error::to_io_error) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix incorrect path to to_io_error
.
utils::to_io_error::to_io_error
is invalid; use the imported to_io_error
.
Apply:
#[cfg(not(unix))]
{
- fs::create_dir_all(path).map_err(utils::to_io_error::to_io_error)
+ fs::create_dir_all(path).map_err(to_io_error)
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
#[cfg(not(unix))] | |
{ | |
fs::create_dir_all(path).map_err(utils::to_io_error::to_io_error) | |
} | |
#[cfg(not(unix))] | |
{ | |
fs::create_dir_all(path).map_err(to_io_error) | |
} |
🤖 Prompt for AI Agents
In packages/ui/api/stellar/src/utils/dir.rs around lines 18 to 21, the call uses
an incorrect path `utils::to_io_error::to_io_error`; replace that
fully-qualified path with the imported function name `to_io_error` (i.e., call
fs::create_dir_all(path).map_err(to_io_error)) so the compiler uses the
already-imported helper rather than an invalid module path.
pub fn join_and_assert_inside(root: &Path, rel: &Path) -> Result<PathBuf, IoError> { | ||
let full = root.join(rel); | ||
if !full.starts_with(root) { | ||
return Err(IoError::other("Path escape root")); | ||
} | ||
Ok(full) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Path traversal check is insufficient (lexical starts_with).
root.join("../escape")
still starts with root
lexically. Reject absolute paths and any ..
, Prefix
, or RootDir
components up front.
pub fn join_and_assert_inside(root: &Path, rel: &Path) -> Result<PathBuf, IoError> {
- let full = root.join(rel);
- if !full.starts_with(root) {
- return Err(IoError::other("Path escape root"));
- }
- Ok(full)
+ // Reject obvious escapes before joining.
+ if rel.is_absolute()
+ || rel
+ .components()
+ .any(|c| matches!(c, Component::ParentDir | Component::Prefix(_) | Component::RootDir))
+ {
+ return Err(IoError::new(
+ IoErrorKind::InvalidInput,
+ "path escapes root or is absolute",
+ ));
+ }
+ let full = root.join(rel);
+ if !full.starts_with(root) {
+ return Err(IoError::new(IoErrorKind::InvalidInput, "path escapes root"));
+ }
+ Ok(full)
}
If this is used with untrusted archive entries, please run:
🏁 Script executed:
#!/bin/bash
# Find callsites and nearby usage context
rg -nC3 --type=rust '\bjoin_and_assert_inside\s*\('
Length of output: 1247
Reject path-traversal escapes before joining (critical)
Lexical starts_with after root.join(rel) is insufficient — a rel containing ..
, absolute, Prefix
, or RootDir
components can escape. This function is called at packages/ui/api/stellar/src/environment/zip_folder.rs:59 with untrusted zip entries; fix is required.
pub fn join_and_assert_inside(root: &Path, rel: &Path) -> Result<PathBuf, IoError> {
- let full = root.join(rel);
- if !full.starts_with(root) {
- return Err(IoError::other("Path escape root"));
- }
- Ok(full)
+ // Reject obvious escapes before joining.
+ if rel.is_absolute()
+ || rel
+ .components()
+ .any(|c| matches!(c, Component::ParentDir | Component::Prefix(_) | Component::RootDir))
+ {
+ return Err(IoError::new(
+ IoErrorKind::InvalidInput,
+ "path escapes root or is absolute",
+ ));
+ }
+ let full = root.join(rel);
+ if !full.starts_with(root) {
+ return Err(IoError::new(IoErrorKind::InvalidInput, "path escapes root"));
+ }
+ Ok(full)
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
pub fn join_and_assert_inside(root: &Path, rel: &Path) -> Result<PathBuf, IoError> { | |
let full = root.join(rel); | |
if !full.starts_with(root) { | |
return Err(IoError::other("Path escape root")); | |
} | |
Ok(full) | |
} | |
pub fn join_and_assert_inside(root: &Path, rel: &Path) -> Result<PathBuf, IoError> { | |
// Reject obvious escapes before joining. | |
if rel.is_absolute() | |
|| rel | |
.components() | |
.any(|c| matches!(c, Component::ParentDir | Component::Prefix(_) | Component::RootDir)) | |
{ | |
return Err(IoError::new( | |
IoErrorKind::InvalidInput, | |
"path escapes root or is absolute", | |
)); | |
} | |
let full = root.join(rel); | |
if !full.starts_with(root) { | |
return Err(IoError::new(IoErrorKind::InvalidInput, "path escapes root")); | |
} | |
Ok(full) | |
} |
let globset = build_globset(&["*.rs"]).unwrap(); | ||
let matcher = globset.matches("main.rs"); | ||
assert!(!matcher.is_empty()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix type mismatch: build_globset expects Vec, not &[&str].
Current tests won’t compile against the function signature.
Apply this diff:
- let globset = build_globset(&["*.rs"]).unwrap();
+ let globset = build_globset(vec!["*.rs".into()]).unwrap();
@@
- let globset = build_globset(&["*.rs"]).unwrap();
+ let globset = build_globset(vec!["*.rs".into()]).unwrap();
@@
- let globset = build_globset(&["*.rs", "*.txt"]).unwrap();
+ let globset = build_globset(vec!["*.rs".into(), "*.txt".into()]).unwrap();
@@
- let globset = build_globset(&[]).unwrap();
+ let globset = build_globset(Vec::<String>::new()).unwrap();
@@
- let result = build_globset(&["[invalid"]);
+ let result = build_globset(vec!["[invalid".into()]);
@@
- let globset = build_globset(&["src/*"]).unwrap();
+ let globset = build_globset(vec!["src/*".into()]).unwrap();
@@
- let globset = build_globset(&["file?.rs"]).unwrap();
+ let globset = build_globset(vec!["file?.rs".into()]).unwrap();
Alternatively, generalize build_globset
to accept impl IntoIterator<Item: AsRef<str>>
and keep tests unchanged.
Also applies to: 12-14, 19-23, 27-29, 33-35, 39-42, 46-50
'process.env.FARGATE_HOST': JSON.stringify( | ||
production ? 'TODO' : `http://localhost:${process.env.FARGATE_PORT || 8888}`, | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Production FARGATE_HOST is 'TODO' — will break prod calls.
Resolve from env at build time or default to empty (relative) like API_HOST
.
- 'process.env.FARGATE_HOST': JSON.stringify(
- production ? 'TODO' : `http://localhost:${process.env.FARGATE_PORT || 8888}`,
- ),
+ 'process.env.FARGATE_HOST': JSON.stringify(
+ process.env.FARGATE_HOST || (production ? '' : `http://localhost:${process.env.FARGATE_PORT || 8888}`)
+ ),
Ensure packages/ui/.env.example
documents FARGATE_HOST and CI injects it for production builds.
🏁 Script executed:
#!/bin/bash
set -euo pipefail
search() {
pattern="$1"
if command -v rg >/dev/null 2>&1; then
rg -n --hidden --no-ignore-vcs -S "$pattern" || true
else
grep -RIn --line-number --exclude-dir=node_modules --exclude-dir=.git --binary-files=without-match "$pattern" . || true
fi
}
echo "PWD: $(pwd)"
echo
echo "=== Search for FARGATE_HOST occurrences ==="
search 'FARGATE_HOST'
echo
echo "=== Search for process.env.FARGATE_HOST occurrences ==="
search 'process.env.FARGATE_HOST'
echo
echo "=== Show packages/ui/rollup.config.mjs (lines 120-140) ==="
if [ -f packages/ui/rollup.config.mjs ]; then
sed -n '120,140p' packages/ui/rollup.config.mjs
else
echo "MISSING: packages/ui/rollup.config.mjs"
fi
echo
echo "=== Show packages/ui/rollup.config.mjs (full file head up to 400 lines for context) ==="
if [ -f packages/ui/rollup.config.mjs ]; then
sed -n '1,400p' packages/ui/rollup.config.mjs
fi
echo
echo "=== packages/ui/.env.example (first 200 lines) ==="
if [ -f packages/ui/.env.example ]; then
sed -n '1,200p' packages/ui/.env.example
else
echo "MISSING: packages/ui/.env.example"
fi
echo
echo "=== Search .github/workflows and CI files for FARGATE_HOST or env injection ==="
if [ -d .github/workflows ]; then
search '.github/workflows'
fi
search 'FARGATE_HOST'
search 'FARGATE'
echo
echo "=== Search for API_HOST usage (to compare pattern) ==="
search 'API_HOST'
Length of output: 6742
Fix production FARGATE_HOST — don't ship 'TODO'
rollup sets process.env.FARGATE_HOST to 'TODO' in production (will break prod requests). Use the real env var or an empty (relative) fallback and ensure CI injects it.
Location: packages/ui/rollup.config.mjs (around lines 131–133)
- 'process.env.FARGATE_HOST': JSON.stringify(
- production ? 'TODO' : `http://localhost:${process.env.FARGATE_PORT || 8888}`,
- ),
+ 'process.env.FARGATE_HOST': JSON.stringify(
+ process.env.FARGATE_HOST || (production ? '' : `http://localhost:${process.env.FARGATE_PORT || 8888}`)
+ ),
- packages/ui/.env.example already documents FARGATE_HOST (packages/ui/.env.example:4); ensure CI injects FARGATE_HOST for production builds.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
'process.env.FARGATE_HOST': JSON.stringify( | |
production ? 'TODO' : `http://localhost:${process.env.FARGATE_PORT || 8888}`, | |
), | |
'process.env.FARGATE_HOST': JSON.stringify( | |
process.env.FARGATE_HOST || (production ? '' : `http://localhost:${process.env.FARGATE_PORT || 8888}`) | |
), |
🤖 Prompt for AI Agents
In packages/ui/rollup.config.mjs around lines 132–134, the build currently
injects the literal string 'TODO' for process.env.FARGATE_HOST in production
which will break prod requests; replace that hardcoded value with the actual
environment variable (use process.env.FARGATE_HOST) and provide a safe fallback
(e.g., an empty string or relative URL) before JSON.stringify, and update CI to
ensure FARGATE_HOST is set for production builds (per packages/ui/.env.example).
try { | ||
isDownloadingScaffold = true; | ||
|
||
const { | ||
ok, | ||
status, | ||
body: scaffoldProject, | ||
} = await fetch(`${fargateHost}/stellar/upgrade-scaffold`, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
body: await zipRustProjectBlob(contract, opts), | ||
}); | ||
|
||
if (!ok) throw new Error(`HTTP ${status}`); | ||
|
||
saveAs(await new Response(scaffoldProject).blob(), 'scaffold-project.zip'); | ||
await postConfig(opts, 'download-file', language); | ||
|
||
isDownloadingScaffold = false; | ||
} catch (error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix content-type, reset error state, and simplify response handling.
The request sends a binary Blob but advertises JSON, and the response handling via Response(body).blob()
is brittle. Also, the error flag isn’t cleared before a retry.
Apply this diff:
try {
- isDownloadingScaffold = true;
-
- const {
- ok,
- status,
- body: scaffoldProject,
- } = await fetch(`${fargateHost}/stellar/upgrade-scaffold`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: await zipRustProjectBlob(contract, opts),
- });
-
- if (!ok) throw new Error(`HTTP ${status}`);
-
- saveAs(await new Response(scaffoldProject).blob(), 'scaffold-project.zip');
+ downloadScaffoldError = false;
+ isDownloadingScaffold = true;
+
+ const endpoint = fargateHost
+ ? new URL('/stellar/upgrade-scaffold', fargateHost).toString()
+ : '/stellar/upgrade-scaffold';
+
+ const resp = await fetch(endpoint, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/zip',
+ },
+ body: await zipRustProjectBlob(contract, opts),
+ });
+
+ if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
+
+ const zipBlob = await resp.blob();
+ saveAs(zipBlob, 'scaffold-project.zip');
await postConfig(opts, 'download-file', language);
isDownloadingScaffold = false;
} catch (error) {
console.log(error);
downloadScaffoldError = true;
isDownloadingScaffold = false;
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
try { | |
isDownloadingScaffold = true; | |
const { | |
ok, | |
status, | |
body: scaffoldProject, | |
} = await fetch(`${fargateHost}/stellar/upgrade-scaffold`, { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
}, | |
body: await zipRustProjectBlob(contract, opts), | |
}); | |
if (!ok) throw new Error(`HTTP ${status}`); | |
saveAs(await new Response(scaffoldProject).blob(), 'scaffold-project.zip'); | |
await postConfig(opts, 'download-file', language); | |
isDownloadingScaffold = false; | |
} catch (error) { | |
try { | |
downloadScaffoldError = false; | |
isDownloadingScaffold = true; | |
const endpoint = fargateHost | |
? new URL('/stellar/upgrade-scaffold', fargateHost).toString() | |
: '/stellar/upgrade-scaffold'; | |
const resp = await fetch(endpoint, { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/zip', | |
}, | |
body: await zipRustProjectBlob(contract, opts), | |
}); | |
if (!resp.ok) throw new Error(`HTTP ${resp.status}`); | |
const zipBlob = await resp.blob(); | |
saveAs(zipBlob, 'scaffold-project.zip'); | |
await postConfig(opts, 'download-file', language); | |
isDownloadingScaffold = false; | |
} catch (error) { | |
console.log(error); | |
downloadScaffoldError = true; | |
isDownloadingScaffold = false; | |
} |
🤖 Prompt for AI Agents
In packages/ui/src/stellar/App.svelte around lines 93 to 114, the request
currently advertises JSON while sending a binary Blob, the response handling via
Response(body).blob() is brittle, and the error flag isn’t reset before retries;
change the request Content-Type to a binary type like application/zip or
application/octet-stream, stop destructuring the fetch result into body and
instead capture the full response object (await fetch...), check response.ok and
status, then call await response.blob() to get the file and pass that to saveAs;
also reset isDownloadError = false before starting the download (or clear it on
success) and ensure isDownloadingScaffold is cleared in a finally block so error
state is reset for retries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@CoveMB I reviewed the changed Stylus files, those look ok.
Are there any changes that indirectly affect Stylus logic that I should take a look at?
Summary
packages/ui/api/ai
module.Key Changes
packages/ui/api/stellar
with routes, controllers, utils, and tests.GET /health
and upgrade/scaffold routes (seesrc/routes /*
andsrc/controllers/*
).Dockerfile.dev
,Dockerfile.prod
,.dockerignore
,README.md
,rustfmt.toml
, andCargo.toml/lock
.packages/ui/api/stellar/tests/*
.packages/ui/api/*
topackages/ui/api/ai/*
:packages/ui/api/ai/ai-assistant/*
.packages/ui/api/ai/development-server.ts
.packages/ui/api/ai/.env.example
andDockerfile.dev
.packages/ui/api/docker-compose.yaml
to orchestrate local API components.
.github/workflows/docker-stg.yaml
,.github/workflows/docker-prod.yaml
..github/actions/oidc/action.yaml
.packages/core/stellar/src/zip-rust.ts
update.packages/core/stellar/zip-env-rust.js
to package Rust env/scaffold artifacts.update-scarb-project.ts
,erc20.ts
, and assorted test updates.packages/core/cairo_alpha/CHANGELOG.md
.packages/ui/.env.example
updated with keys used by the new layout..gitignore
,.prettierignore
,package.json
,netlify.toml
,.vscode/*
,rollup.config.mjs
).yarn.lock
.Breaking/Structural Changes
packages/ui/api/ai
. Any imports or tooling referencing the oldpackages/ui/api/*
paths must be updated to the new location.How to Run (Local)
packages/ui/api/stellar
:cargo run
(dev) or build with Docker:doc ker build -f Dockerfile.dev .
GET /health
packages/ui/api/ai
:deno task dev
(seedeno.json
anddevelopment -server.ts
)packages/ui/api
:docker compose up --build
.env.example
to.env
inpackages/ui
,packages/ui/api/ai
, andpackages/ui/api/stellar
as needed.Security/Infra
Testing/Verification
packages/ui/api/stellar/ tests/*
.GET /health
returns healthy.set).
Scope/Risk