pallets/flask
Input boundaries are the WSGI environ, the process environment (`FLASK_*`, dotenv files), config files, and the request cookie jar. A WSGI environ becomes a `Request` in `AppContext.from_environ`, which also stamps `request.json_module = app.json` so body JSON decoding uses the app's provider. The `AppContext` is the single state owner for the duration of a request: it holds `g`, the lazily opened session, the bound `MapAdapter`, collected `after_this_request` callbacks and cached flashes. Output boundaries are the `Response` returned to the WSGI server, the `Set-Cookie` session header written in `process_response`, rendered template strings, and log records emitted to `wsgi.errors` or stderr. Config flows one way: `default_config` → `Config` dict → `ConfigAttribute` descriptors (`app.testing`, `app.secret_key`, `app.permanent_session_lifetime`) and per-request property lookups on `Request`/`Response`.
- The environ→Request transform happens in `AppContext.from_environ`, which constructs `app.request_class(environ)` and immediately assigns `request.json_module = app.json`, so `request.get_json()` uses the app's JSON provider rather than stdlib json.
- The URL adapter is built in `AppContext.__init__` (not at push time) via `app.create_url_adapter`, and any `HTTPException` raised there is stashed on `request.routing_exception` instead of propagating.
- `create_url_adapter` applies `TRUSTED_HOSTS` to `request.trusted_hosts` and then recomputes `request.host` through `werkzeug.wsgi.get_host` before binding — host validation happens on this path, before routing.
- Session data flows cookie → `SecureCookieSessionInterface.open_session` → `URLSafeTimedSerializer.loads(val, max_age=PERMANENT_SESSION_LIFETIME)` → `SecureCookieSession`; a `BadSignature` silently yields a fresh empty session rather than an error.
- Session writes are deferred to `process_response`, which calls `save_session` only when `is_null_session` is false, and `save_session` adds `Vary: Cookie` whenever `session.accessed` is set, deletes the cookie when an emptied session is modified, and otherwise gates on `should_set_cookie`.
- Session values are serialized by `TaggedJSONSerializer`, which round-trips non-JSON Python types through single-key tag dicts — ` di` (dict), ` t` (tuple), ` b` (base64 bytes), ` m` (Markup), ` u` (UUID), ` d` (http-date datetime).
- Config resolution order is `default_config` copy → `DEBUG` overwritten from `get_debug_flag()` (the `FLASK_DEBUG` env var) → `Config(root_path, defaults)`, with `root_path` swapped to `instance_path` when `instance_relative_config=True`.
- Env-file input precedence is: variables already in `os.environ` win, then `-e/--env-file`, then `.env`, then `.flaskenv` — implemented by merging dicts in that order in `load_dotenv` and skipping keys already present in `os.environ`.
- Per-request body limits read through `current_app.config` at access time rather than being copied onto the request: `max_content_length`, `max_form_memory_size` and `max_form_parts` each check a private override, then fall back to `MAX_CONTENT_LENGTH` / `MAX_FORM_MEMORY_SIZE` (500_000) / `MAX_FORM_PARTS` (1_000).
- Template context is assembled in `update_template_context`: app-level then reversed blueprint-level context processors run, and the caller's explicit `render_template(**context)` values are re-applied last from a saved copy so they always win.
- The default template context processor replaces the `request` and `g` proxies with concrete objects for speed but deliberately leaves `session` as a proxy, because touching it would set `session.accessed` and force a `Vary: Cookie` header.
- `send_file`/`send_from_directory` funnel through `_prepare_send_file_kwargs`, which injects `environ`, `USE_X_SENDFILE`, `response_class`, `_root_path` and defaults `max_age` to `app.get_send_file_max_age` before delegating to Werkzeug.
- Log output is routed by the `wsgi_errors_stream` LocalProxy: inside a request it writes to `request.environ["wsgi.errors"]`, otherwise `sys.stderr`; `create_logger` attaches `default_handler` only when no handler in the chain already covers the effective level.
- Blueprint registration is a data-merge step, not a live delegation: `_merge_blueprint_funcs` copies the blueprint's error handler spec, view functions, before/after/teardown lists, url defaults, url value preprocessors and template context processors into the app's dicts under the dotted name.