# HTTP(S) modules Import modules directly or through a local import map: ```ts import { value } from "https://example.com/lib/mod.ts"; ``` URLs can also be entry points: ```sh avril run https://example.com/app/main.ts avril update https://example.com/app/main.ts ``` Static imports are acquired before execution. Computed dynamic imports acquire and prepare their static dependencies asynchronously. Relative and root-relative imports resolve against the final response URL after redirects. Remote modules do not inherit local package aliases or resolve filesystem imports; explicit `jsr:` and `avril:` imports remain available. Module identity and `import.meta.url` use the requested URL, not the cache path or redirect destination. Queries and fragments distinguish module identities; fragments are not sent to the server. Consequently, constructing a URL relative to `import.meta.url` can differ from a relative import after a redirect. TypeScript is transpiled according to the final URL's `.ts` or `.mts` extension, ignoring its query and fragment. Content-Type does not select the source language. Registry URLs retain JSR's manifest verification and package confinement. ## Cache and integrity HTTP sources are reused until `avril update`. The cache defaults to `$AVRIL_CACHE_DIR`, `$XDG_CACHE_HOME/avril`, or `$HOME/.cache/avril`, with `--cache-dir=PATH` as an override. Source blobs are content-addressed; updating one project does not overwrite another project's pinned source. The root `avril.lock` records the SHA-256 checksum and final response URL for each requested URL. Successful graph preparation saves new pins; `update` explicitly replaces encountered HTTP pins. If a pinned source is missing from the cache, an online download must match both its checksum and final URL. Corrupt cached sources fail integrity checks rather than silently being replaced. `--offline` prohibits downloads. `--frozen` requires existing pins and does not modify the lockfile. `cache`, `info`, `--include`, pruning, vendoring, and editor support also work with HTTP sources. Vendor trees store sources beneath `http/`; the lockfile supplies their checksums and redirect bases for offline use. ## Permissions and redirects Acquisition uses host tooling authority, independently of guest `net`, `read`, and `write` permissions. Each requested module needs `js-exec` authority, even on cache hits. Like local entry files, a URL entry point receives an exact execution grant; explicit denials still override it. Redirect chains check execution permission only for the initial requested URL, not the destinations. Granting a URL therefore trusts its server to redirect to any HTTP(S) destination, including other origins and local services. A denial for a destination does not block a redirect to it. Relative dependencies resolve to their own requested URLs and need their own execution grants. The initial URL's execution permission is rechecked during asynchronous work and before linking cached modules, so revocation still takes effect. Redirects are limited to ten hops. Credentials and non-HTTP(S) destinations are rejected; responses are bounded to 32 MiB and downloads to 30 seconds. HTML responses are rejected as modules. ## HTTP(S) packages A directory URL ending with `/` in `deps` fetches `avril.conf` beneath that URL: ```text deps: [ 'https://example.com/math/', {from: 'https://example.com/format/', name: 'format'}, ], ``` The first entry binds the package's declared `name`; the second overrides it. Import that binding or an exported subpath, just like a local package. The remote config uses the same schema, including exact `exports`, self-imports, `imports`, `scopes`, and private `deps`. Relative remote dependencies are directory URLs too: `'../numeric/'`. Remote configs cannot declare filesystem dependencies. Exports and config-relative targets resolve against the config's final response URL after redirects. Export targets must stay within that URL's package directory; redirects follow the ordinary HTTP module rules. Dependencies do not grant execution permission to their exports or transitive dependencies. The requested config URL requires `js-exec` permission, including when reading a dependency's declared name and on cache hits. A directory URL execution grant covers its config and modules. Configs and sources are pinned together in `avril.lock`; `update`, `--offline`, `--frozen`, pruning, and vendoring apply to both. Package ownership follows the importing module's config, not a global registry. A package export starts in that package. Other URL imports match the importing package's declared HTTP dependencies or its own requested/final directory, choosing the most specific match. Nested package boundaries must be declared in the parent package's `deps`; their configs are loaded only when a module crosses that boundary. An unrelated package's private dependencies cannot change another module's maps. Each requested module URL keeps its first owner, including plain modules. Reaching the same URL with a different owner is an explicit conflict, never a silent rebind. Redirected package aliases share ownership only when their final config URL, pinned contents, and module ownership region agree. Modules beneath the final package directory inherit only that canonical region, not an alias's requested directory. Other modules inherit their matching requested directory. All requested config URLs that have claimed a canonical package remain required execution authorities; revoking any of them blocks subsequent imports through every alias. Ordinary redirects still resolve relative imports and scopes against the module's final response URL. avril does not probe remote ancestors for configs. Direct URL imports beneath a declared dependency require that dependency's config and its execution permission; imports from plain remote modules have no package context. Trailing-slash URLs are package syntax in `deps`, not a change to direct URL entry points. URLs beneath the configured JSR registry are reserved for registry packages, not HTTP configs. An unused dependency whose name must be inferred still needs its config at package initialization. Network, cache, or permission failures are fatal for execution; the language server instead reports package errors and unresolved imports.