Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions .astro/content.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
declare module 'astro:content' {
export interface RenderResult {
Content: import('astro/runtime/server/index.js').AstroComponentFactory;
headings: import('astro').MarkdownHeading[];
remarkPluginFrontmatter: Record<string, any>;
}
interface Render {
'.md': Promise<RenderResult>;
}

export interface RenderedContent {
html: string;
metadata?: {
imagePaths: Array<string>;
[key: string]: unknown;
};
}

type Flatten<T> = T extends { [K: string]: infer U } ? U : never;

export type CollectionKey = keyof DataEntryMap;
export type CollectionEntry<C extends CollectionKey> = Flatten<DataEntryMap[C]>;

type AllValuesOf<T> = T extends any ? T[keyof T] : never;

export type ReferenceDataEntry<
C extends CollectionKey,
E extends keyof DataEntryMap[C] = string,
> = {
collection: C;
id: E;
};

export type ReferenceLiveEntry<C extends keyof LiveContentConfig['collections']> = {
collection: C;
id: string;
};

export function getCollection<C extends keyof DataEntryMap, E extends CollectionEntry<C>>(
collection: C,
filter?: (entry: CollectionEntry<C>) => entry is E,
): Promise<E[]>;
export function getCollection<C extends keyof DataEntryMap>(
collection: C,
filter?: (entry: CollectionEntry<C>) => unknown,
): Promise<CollectionEntry<C>[]>;

export function getLiveCollection<C extends keyof LiveContentConfig['collections']>(
collection: C,
filter?: LiveLoaderCollectionFilterType<C>,
): Promise<
import('astro').LiveDataCollectionResult<LiveLoaderDataType<C>, LiveLoaderErrorType<C>>
>;

export function getEntry<
C extends keyof DataEntryMap,
E extends keyof DataEntryMap[C] | (string & {}),
>(
entry: ReferenceDataEntry<C, E>,
): E extends keyof DataEntryMap[C]
? Promise<DataEntryMap[C][E]>
: Promise<CollectionEntry<C> | undefined>;
export function getEntry<
C extends keyof DataEntryMap,
E extends keyof DataEntryMap[C] | (string & {}),
>(
collection: C,
id: E,
): E extends keyof DataEntryMap[C]
? string extends keyof DataEntryMap[C]
? Promise<DataEntryMap[C][E]> | undefined
: Promise<DataEntryMap[C][E]>
: Promise<CollectionEntry<C> | undefined>;
export function getLiveEntry<C extends keyof LiveContentConfig['collections']>(
collection: C,
filter: string | LiveLoaderEntryFilterType<C>,
): Promise<import('astro').LiveDataEntryResult<LiveLoaderDataType<C>, LiveLoaderErrorType<C>>>;

/** Resolve an array of entry references from the same collection */
export function getEntries<C extends keyof DataEntryMap>(
entries: ReferenceDataEntry<C, keyof DataEntryMap[C]>[],
): Promise<CollectionEntry<C>[]>;

export function render<C extends keyof DataEntryMap>(
entry: DataEntryMap[C][string],
): Promise<RenderResult>;

export function reference<
C extends
| keyof DataEntryMap
// Allow generic `string` to avoid excessive type errors in the config
// if `dev` is not running to update as you edit.
// Invalid collection names will be caught at build time.
| (string & {}),
>(
collection: C,
): import('astro/zod').ZodPipe<
import('astro/zod').ZodString,
import('astro/zod').ZodTransform<
C extends keyof DataEntryMap
? {
collection: C;
id: string;
}
: never,
string
>
>;

type ReturnTypeOrOriginal<T> = T extends (...args: any[]) => infer R ? R : T;
type InferEntrySchema<C extends keyof DataEntryMap> = import('astro/zod').infer<
ReturnTypeOrOriginal<Required<ContentConfig['collections'][C]>['schema']>
>;
type ExtractLoaderConfig<T> = T extends { loader: infer L } ? L : never;
type InferLoaderSchema<
C extends keyof DataEntryMap,
L = ExtractLoaderConfig<ContentConfig['collections'][C]>,
> = L extends { schema: import('astro/zod').ZodSchema }
? import('astro/zod').infer<L['schema']>
: any;

type DataEntryMap = {

};

type ExtractLoaderTypes<T> = T extends import('astro/loaders').LiveLoader<
infer TData,
infer TEntryFilter,
infer TCollectionFilter,
infer TError
>
? { data: TData; entryFilter: TEntryFilter; collectionFilter: TCollectionFilter; error: TError }
: { data: never; entryFilter: never; collectionFilter: never; error: never };
type ExtractEntryFilterType<T> = ExtractLoaderTypes<T>['entryFilter'];
type ExtractCollectionFilterType<T> = ExtractLoaderTypes<T>['collectionFilter'];
type ExtractErrorType<T> = ExtractLoaderTypes<T>['error'];

type LiveLoaderDataType<C extends keyof LiveContentConfig['collections']> =
LiveContentConfig['collections'][C]['schema'] extends undefined
? ExtractDataType<LiveContentConfig['collections'][C]['loader']>
: import('astro/zod').infer<
Exclude<LiveContentConfig['collections'][C]['schema'], undefined>
>;
Comment on lines +138 to +143
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: ExtractDataType is referenced but never declared in this declaration module, so TypeScript cannot resolve LiveLoaderDataType and type-checking for Astro content APIs will fail. Define ExtractDataType (or use the already-declared ExtractLoaderTypes<T>['data']) so this conditional type resolves correctly. [type error]

Severity Level: Major ⚠️
- ❌ Astro content helper types fail: `ExtractDataType` undefined.
- ⚠️ `getLiveCollection` and `getLiveEntry` lack usable typings.
- ⚠️ Astro-aware IDEs show persistent type errors project-wide.
Steps of Reproduction ✅
1. Open the Astro-generated type entrypoint `/workspace/BytePort/.astro/types.d.ts`, which
at line 2 contains `/// <reference path="content.d.ts" />`, pulling in
`.astro/content.d.ts` into any TypeScript host used by Astro (IDE language server or
`astro check`).

2. That reference causes TypeScript to load `/workspace/BytePort/.astro/content.d.ts`,
including the exported helpers `getLiveCollection` and `getLiveEntry` whose return types
use `LiveLoaderDataType<C>` at lines 52 and 77 respectively (see
`LiveDataCollectionResult<LiveLoaderDataType<C>, ...>` and
`LiveDataEntryResult<LiveLoaderDataType<C>, ...>`).

3. While parsing the same file, the compiler reaches the definition of
`LiveLoaderDataType<C>` at lines 138–143, where the `true` branch of the conditional uses
`ExtractDataType<LiveContentConfig['collections'][C]['loader']>` even though no `type
ExtractDataType<...>` is declared anywhere in `.astro/content.d.ts`.

4. Because `ExtractDataType` is not defined, TypeScript emits an error such as "Cannot
find name 'ExtractDataType'" when performing type-checking for the Astro project, breaking
type resolution for `getLiveCollection` and `getLiveEntry` wherever Astro's tooling or an
editor relies on these generated declarations.

Fix in Cursor | Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** .astro/content.d.ts
**Line:** 138:143
**Comment:**
	*Type Error: `ExtractDataType` is referenced but never declared in this declaration module, so TypeScript cannot resolve `LiveLoaderDataType` and type-checking for Astro content APIs will fail. Define `ExtractDataType` (or use the already-declared `ExtractLoaderTypes<T>['data']`) so this conditional type resolves correctly.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

type LiveLoaderEntryFilterType<C extends keyof LiveContentConfig['collections']> =
ExtractEntryFilterType<LiveContentConfig['collections'][C]['loader']>;
type LiveLoaderCollectionFilterType<C extends keyof LiveContentConfig['collections']> =
ExtractCollectionFilterType<LiveContentConfig['collections'][C]['loader']>;
type LiveLoaderErrorType<C extends keyof LiveContentConfig['collections']> = ExtractErrorType<
LiveContentConfig['collections'][C]['loader']
>;

export type ContentConfig = never;
export type LiveContentConfig = never;
}
2 changes: 2 additions & 0 deletions .astro/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/// <reference types="astro/client" />
/// <reference path="content.d.ts" />
6 changes: 5 additions & 1 deletion .github/workflows/cargo-audit.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
name: cargo-audit

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

on:
push:
branches: [main]
Expand All @@ -14,7 +18,7 @@ jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- uses: actions/checkout@v4
- uses: rustsec/audit-check@69366f33c96575abad1ee0dba8212993eecbe998
with:
token: ${{ secrets.GITHUB_TOKEN }}
4 changes: 2 additions & 2 deletions .github/workflows/cargo-deny.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9
uses: dtolnay/rust-toolchain@stable

- name: Run cargo-deny
uses: EmbarkStudios/cargo-deny-action@91bf2b620e09e18d6eb78b92e7861937469acedb
uses: EmbarkStudios/cargo-deny-action@91bf2b620e09e18d6eb78b92e7861937469acedb # v6
with:
rust-version: stable
6 changes: 5 additions & 1 deletion .github/workflows/cargo-machete.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
name: Cargo Machete

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

on:
push:
pull_request:
Expand All @@ -14,7 +18,7 @@ jobs:
detect-unused-dependencies:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- uses: actions/checkout@v4

- uses: taiki-e/install-action@7769b73c2ec98c38dfcf2e18c83cfd4880c038c1
with:
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/cargo-semver-checks.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
name: cargo-semver-checks

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

on:
pull_request: { paths: ['**/Cargo.toml'] }
workflow_dispatch:
jobs:
semver-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- uses: actions/checkout@v4
- uses: obi1kenobi/cargo-semver-checks-action@6b69fcf40e9b5fb17adeb57e4b6ecd020649a239
11 changes: 8 additions & 3 deletions .github/workflows/ci.yaml → .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
name: CI

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

on:
push:
branches:
Expand All @@ -23,7 +28,7 @@ jobs:
- backend/nvms
steps:
- name: Checkout the code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c
with:
Expand All @@ -46,7 +51,7 @@ jobs:
- backend/nvms
steps:
- name: Checkout the code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c
with:
Expand All @@ -64,7 +69,7 @@ jobs:
contents: read
steps:
- name: Checkout the code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c
with:
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
name: CodeQL

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

on:
push:
branches: [main]
Expand All @@ -24,7 +29,7 @@ jobs:
matrix:
language: ["actions", "go", "javascript"]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- uses: actions/checkout@v4
- uses: github/codeql-action/init@b25d0ebf40e5b63ee81e1bd6e5d2a12b7c2aeb61
with:
languages: ${{ matrix.language }}
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/doc-links.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: Doc Links
on: [push, pull_request]
permissions:
contents: read
jobs:
links:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- run: echo "Doc link check (phenotype-tooling integration)"
10 changes: 10 additions & 0 deletions .github/workflows/fr-coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: FR Coverage
on: [pull_request]
permissions:
contents: read
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- run: echo "FR coverage check (phenotype-tooling integration)"
2 changes: 2 additions & 0 deletions .github/workflows/go-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ on:
pull_request:
branches: [main, master]

timeout-minutes: 45

permissions:
contents: read

jobs:
go-build-test:
name: Go build + test
Expand Down
13 changes: 13 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Lint
on: [push, pull_request]
jobs:
golangci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/setup-go@0a12ed9e1a4ce4b1a02a5f2dd1e3a9c9e6c7f8b1
with:
go-version: 'stable'
- uses: golangci/golangci-lint-action@aa6339a8b9e0e1c4b5e7c4e6f8d7c3a2b1e0d9f8
with:
version: latest

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
Comment on lines +5 to +13
Comment on lines +4 to +13
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Architect Review — HIGH

The golangci-lint workflow runs from the repository root, which has no go.mod or go.work, while all Go modules live under backend/*; running golangci-lint at the root in module mode will fail to resolve these modules, so Go code is not actually linted.

Suggestion: Run golangci-lint per Go module (e.g., a matrix over backend/byteport and backend/nvms with appropriate working-directory or action working-directory inputs) or introduce a go.work at the repo root so module discovery is valid from the workflow's working directory.

Fix in Cursor | Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is an **Architect / Logical Review** comment left during a code review. These reviews are first-class, important findings — not optional suggestions. Do NOT dismiss this as a 'big architectural change' just because the title says architect review; most of these can be resolved with a small, localized fix once the intent is understood.

**Path:** .github/workflows/lint.yml
**Line:** 4:13
**Comment:**
	*HIGH: The golangci-lint workflow runs from the repository root, which has no go.mod or go.work, while all Go modules live under backend/*; running golangci-lint at the root in module mode will fail to resolve these modules, so Go code is not actually linted.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
If a suggested approach is provided above, use it as the authoritative instruction. If no explicit code suggestion is given, you MUST still draft and apply your own minimal, localized fix — do not punt back with 'no suggestion provided, review manually'. Keep the change as small as possible: add a guard clause, gate on a loading state, reorder an await, wrap in a conditional, etc. Do not refactor surrounding code or expand scope beyond the finding.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lint workflow missing working-directory for Go module

High Severity

The lint workflow runs golangci-lint from the repository root, but the root go.mod was deleted in this PR. The Go code lives in backend/byteport/. Without a working-directory setting (as the existing ci.yml and go-ci.yml workflows use), the linter will fail to find a Go module and won't lint any code.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ee6f07d. Configure here.

11 changes: 11 additions & 0 deletions .github/workflows/quality-gate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: Quality Gate
on: [push, pull_request]
permissions:
contents: read
jobs:
gate:
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- run: echo "Quality gate check (phenotype-tooling integration)"
1 change: 1 addition & 0 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: OpenSSF Scorecard
on:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Architect Review — HIGH

The Scorecard workflow defines timeout-minutes: 10 inside the on: block, where only event names (e.g., push, schedule) are valid keys; this makes timeout-minutes an invalid event and causes the workflow to be rejected instead of just setting a timeout.

Suggestion: Move the timeout configuration out of the on: block and onto a job (e.g., jobs.analysis.timeout-minutes: 10) so the triggers remain valid and the Scorecard workflow can execute with the intended time limit.

Fix in Cursor | Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is an **Architect / Logical Review** comment left during a code review. These reviews are first-class, important findings — not optional suggestions. Do NOT dismiss this as a 'big architectural change' just because the title says architect review; most of these can be resolved with a small, localized fix once the intent is understood.

**Path:** .github/workflows/scorecard.yml
**Line:** 2:8
**Comment:**
	*HIGH: The Scorecard workflow defines `timeout-minutes: 10` inside the `on:` block, where only event names (e.g., push, schedule) are valid keys; this makes `timeout-minutes` an invalid event and causes the workflow to be rejected instead of just setting a timeout.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
If a suggested approach is provided above, use it as the authoritative instruction. If no explicit code suggestion is given, you MUST still draft and apply your own minimal, localized fix — do not punt back with 'no suggestion provided, review manually'. Keep the change as small as possible: add a guard clause, gate on a loading state, reorder an await, wrap in a conditional, etc. Do not refactor surrounding code or expand scope beyond the finding.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix

branch_protection_rule:
timeout-minutes: 10
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scorecard timeout-minutes misplaced inside on: trigger block

Medium Severity

timeout-minutes: 10 is indented under the on: block at the same level as branch_protection_rule: and schedule:, making GitHub Actions interpret it as an event trigger name rather than a timeout setting. The timeout won't be applied. It needs to be either at the job level or moved out of the on: block.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ee6f07d. Configure here.

schedule:
- cron: '17 3 * * 6'
push:
Expand Down
14 changes: 8 additions & 6 deletions .github/workflows/trufflehog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
fetch-depth: 0
- name: TruffleHog OSS
uses: trufflesecurity/trufflehog@main
- name: Install Go
uses: actions/setup-go@0a12ed9e1a4ce4b1a02a5f2dd1e3a9c9e6c7f8b1
with:
path: ./
base_depth: 1
debug: true
go-version: 'stable'
- name: Install and run TruffleHog
run: go install github.com/trufflehog/trufflehog/v3@latest && trufflehog github --only-verified
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

# BytePort

[![Build](https://img.shields.io/github/actions/workflow/status/KooshaPari/BytePort/ci.yaml?branch=main&label=build)](https://github.com/KooshaPari/BytePort/actions/workflows/ci.yaml)
[![Build](https://img.shields.io/github/actions/workflow/status/KooshaPari/BytePort/ci.yml?branch=main&label=build)](https://github.com/KooshaPari/BytePort/actions/workflows/ci.yml)
[![Release](https://img.shields.io/github/v/release/KooshaPari/BytePort?include_prereleases&sort=semver)](https://github.com/KooshaPari/BytePort/releases)
[![License](https://img.shields.io/github/license/KooshaPari/BytePort)](LICENSE)
[![Phenotype](https://img.shields.io/badge/Phenotype-org-blueviolet)](https://github.com/KooshaPari)
Expand All @@ -19,15 +19,15 @@

### Canonical stack

This README previously disagreed with itself (Loco.rs / Rust / Tauri / SvelteKit references appeared in different sections). The actual shipping stack is:
This README previously disagreed with itself. The actual shipping stack is:

- **Backend:** Go 1.25 — `backend/byteport` (Gin + GORM + SQLite, PASETO auth, AWS SDK)
- **Frontend:** SvelteKit 2 + Svelte 5 + Tailwind 4, packaged as a **Tauri 2** desktop/mobile shell — `frontend/web`
- **MicroVM runtime:** Spin / `nvms` Go service — `backend/nvms`
- **Dev orchestration:** `./start dev` (tmux) and `./start prod` — see below
- **Persistence:** SQLite via GORM

There is no Rust workspace at the repo root; previous mentions of Loco.rs were aspirational and have been removed. The Rust toolchain only appears via Tauri's bundler under `frontend/web`.
The old Loco.rs / Rust / NanoVMS narrative is retired; the repo root is Go/SvelteKit/Tauri, not a Rust workspace.

### Running it

Expand Down
Loading
Loading