diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..0accd7d --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +*.sh text eol=lf +*.cast text eol=lf +*.svg text eol=lf diff --git a/README.md b/README.md index 998e848..06b7b90 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,42 @@ # microcodegen.py -**PRD text → production FastAPI app → ZIP bytes. One Python file, zero dependencies.** +**PRD text → a running Flask app → ZIP bytes. One Python file, zero dependencies.** Inspired by Andrej Karpathy's [micrograd](https://github.com/karpathy/micrograd) — this is the core Archiet algorithm in its simplest form. +[![microcodegen demo — PRD to a running Flask app](demo.svg)](https://archiet.com) + +> Every line of output above is from a real run. Reproduce it yourself in one command: [`./demo.sh`](demo.sh). + ```bash -python microcodegen.py your-prd.md --out ./myapp -cd myapp && pip install -r requirements.txt -alembic upgrade head -uvicorn main:app --reload +python microcodegen.py examples/task_manager.md --out ./my-task-app +cd my-task-app && cp .env.example .env +docker compose up # Flask + Postgres, healthcheck-gated +curl localhost:5000/api/health ``` -→ A **working, bootable FastAPI app** at `http://localhost:8000/docs`. +→ A **working, bootable Flask app** with JWT-cookie auth and per-tenant CRUD at `http://localhost:5000`. --- ## What it generates from your PRD -Given a plain-English Product Requirements Document, `microcodegen.py` outputs a complete FastAPI application: +Given a plain-English Product Requirements Document, `microcodegen.py` outputs a complete Flask application (25 files for the example PRD): -- **FastAPI** with `/docs` interactive OpenAPI explorer — free, auto-generated by FastAPI -- **SQLAlchemy 2.0 models** — one per entity extracted from your PRD (`DeclarativeBase`) -- **Pydantic v2 schemas** — `Base` / `Create` / `Update` / `Response` classes per entity -- **JWT auth** — `/api/auth/register`, `/api/auth/login`, `/api/auth/me` with httpOnly cookies; never localStorage -- **Full CRUD APIRouters** — list, create, get, update, delete per entity; all `Depends(get_current_user)` -- **Per-tenant data isolation** — every row has a `user_id` FK; every query filters by it; no cross-user leaks -- **Alembic migrations** — `alembic.ini` + `alembic/env.py` pre-configured; run `alembic upgrade head` -- **pytest test suite** — `TestClient` with `dependency_overrides`, auto-skips if Postgres unreachable -- **docker-compose.yml** — Postgres 16 with healthcheck-gated app startup -- **ARCHITECTURE.md** — ArchiMate 3.2 element map typed from the genome IR -- **openapi.yaml** — machine-readable API contract; import into Postman or Swagger UI +- **Flask app factory** (`app/__init__.py` → `create_app`) with a `wsgi.py`/gunicorn entrypoint — boots as-is +- **Flask-SQLAlchemy models** — one per entity extracted from your PRD, each with a `user_id` FK and `to_dict()` +- **JWT-cookie auth** — `/api/auth/register`, `/login`, `/logout`, `/me` via flask-jwt-extended; tokens live in **httpOnly cookies**, never localStorage +- **Full CRUD blueprints** — list, create, get, update, delete per entity; every route is `@jwt_required()` +- **Per-tenant data isolation** — every row has a `user_id`; every query is `filter_by(user_id=get_jwt_identity())`; no cross-user leaks. Writes go through a writable-field allowlist so a client can't spoof `user_id` +- **JSON error handlers** (400/401/404/405/500) so the API never returns HTML +- **CORS scoped to `FRONTEND_URL`** (not wildcard), with credentials support +- **A boot-time secret check** — `config.py` refuses to start if `SECRET_KEY`/`JWT_SECRET_KEY` are missing or still a `change-me` placeholder +- **docker-compose.yml** — Postgres 16 with a healthcheck-gated app start +- **A click-through demo page** (`app/static/index.html`) served at `/` — register/login/CRUD in the browser, no frontend to write +- **pytest suite** — Flask test client smoke tests +- **GENOME.json** — the architectural IR the app was rendered from -Zero LLM calls. Zero API keys. Pure Python stdlib. +Schema is created with `db.create_all()` on first boot — this minimal file ships no migrations (the full platform adds Alembic). Zero LLM calls. Zero API keys. Pure Python stdlib. --- @@ -44,11 +49,32 @@ cd microcodegen # Generate from an example PRD python microcodegen.py examples/task_manager.md --out ./my-task-app + +# Boot it (needs Docker for the bundled Postgres) cd my-task-app -pip install -r requirements.txt -alembic upgrade head -uvicorn main:app --reload -# → http://localhost:8000/docs +cp .env.example .env +docker compose up +# → http://localhost:5000 (and the API at /api/health) +``` + +End-to-end in three curls (register → create → list): + +```bash +curl -c cookies.txt -X POST localhost:5000/api/auth/register \ + -H 'Content-Type: application/json' \ + -d '{"email":"you@example.com","password":"hunter22hunter"}' + +curl -b cookies.txt -X POST localhost:5000/api/projects/ \ + -H 'Content-Type: application/json' \ + -d '{"name":"My first project"}' + +curl -b cookies.txt localhost:5000/api/projects/ +``` + +Or just run the whole thing — generate, boot, and walk the auth+CRUD flow: + +```bash +./demo.sh ``` Or pipe the ZIP: @@ -99,14 +125,14 @@ PRD text (your requirements document) │ No LLM. Misses subtle PRDs; that's acceptable for a spec reference. │ ▼ Stage 2: manifest_to_genome(manifest) → genome - │ Converts the manifest into a stack-neutral architectural genome dict. - │ Adds ArchiMate 3.2 element typing (ApplicationComponent, DataObject, - │ BusinessProcess, ApplicationService) for each extracted element. + │ Converts the manifest into a stack-neutral architectural genome dict — + │ the intermediate representation that drives rendering. One module per + │ entity, plus inferred integrations. │ ▼ Stage 3: render_genome(genome) → {path: content} - │ string.Template substitution over embedded FastAPI templates. - │ Outputs SQLAlchemy 2.0 models, Pydantic v2 schemas, APIRouters, - │ Alembic env, pytest suite, ARCHITECTURE.md, openapi.yaml. + │ string.Template substitution over embedded Flask templates. + │ Outputs the app factory, Flask-SQLAlchemy models, JWT-cookie auth, + │ CRUD blueprints, config, docker-compose, tests, and a demo page. │ ▼ Stage 4: pack(files) → ZIP bytes stdlib zipfile.ZipFile. Download it, push it to GitHub, deploy it. @@ -129,14 +155,16 @@ The same philosophy as [micrograd](https://github.com/karpathy/micrograd) and [m ## What this file does NOT include -This is the minimum viable PRD→code pipeline. Production use cases need more: +This is the minimum viable PRD→code pipeline: one stack (Flask), regex extraction, no quality gate. Production use cases need more: | Feature | Where it lives | |---|---| | LLM-powered PRD extraction (handles natural language) | [archiet.com](https://archiet.com) | -| **9 backend stacks**: NestJS, Django, Flask, Go (chi), Java Spring Boot, .NET, Laravel, Rails | [archiet.com](https://archiet.com) | +| **9 backend stacks**: FastAPI, NestJS, Django, Go (chi), Java Spring Boot, .NET, Laravel, Rails | [archiet.com](https://archiet.com) | | React/Next.js frontend (shadcn/ui, auth pages, onboarding) | [archiet.com](https://archiet.com) | | Expo mobile app (iOS + Android, push notifications) | [archiet.com](https://archiet.com) | +| Alembic migrations instead of `db.create_all` | [archiet.com](https://archiet.com) | +| ArchiMate 3.2 element map + ADR / TOGAF architecture docs | [archiet.com](https://archiet.com) | | Compliance artifact packs — SOC 2, HIPAA, GDPR, PCI-DSS control matrices | [archiet.com](https://archiet.com) | | 13-gate shippability audit (security scan, import coherence, boot test) | [archiet.com](https://archiet.com) | | GitHub push + drift detection + architecture scoring | [archiet.com](https://archiet.com) | @@ -161,32 +189,35 @@ The full Archiet pipeline replaces this with a chunked LLM extractor (overlap + ### Stage 2 — `manifest_to_genome(manifest) → genome` -Converts the manifest into a formal **architectural genome** — the stack-neutral intermediate representation that drives all downstream rendering. +Converts the manifest into a **genome** — the stack-neutral intermediate representation that drives all downstream rendering. The genome encodes: -- `language` — `fastapi` (this file's scope; the full system supports 12+ stacks) -- `modules[]` — one module per entity, with entities, user_stories, acceptance_criteria -- `archimate_elements[]` — every extracted element typed to ArchiMate 3.2 (ApplicationComponent for the app itself, DataObject per entity, BusinessProcess for workflow user stories, ApplicationService per integration) +- `language` — `flask` (this file's scope; the full system supports 9+ stacks) +- `modules[]` — one module per entity, with its fields and user stories - `integrations[]` — inferred from vendor mentions (Stripe, Auth0, SendGrid, etc.) +The full platform additionally types every element to ArchiMate 3.2 and threads it through governance and compliance — out of scope for this single file. + ### Stage 3 — `render_genome(genome) → {path: content}` `string.Template` substitution across templates embedded directly in the file. Each template is a complete source file with `$variable` placeholders. -Templates emitted for every generated app: +Files emitted for every generated app: -- `main.py` — FastAPI entry point with `include_router` wiring (no `create_all` — Alembic owns the schema) -- `app/database.py` — SQLAlchemy 2.0 `DeclarativeBase` + `get_db` dependency -- `app/auth.py` — JWT via PyJWT + passlib/bcrypt, httpOnly cookie, `get_current_user` dependency -- `app/models/user.py` — User model -- `alembic.ini` + `alembic/env.py` — migration environment with model auto-discovery -- `ARCHITECTURE.md` — ArchiMate 3.2 element table -- `openapi.yaml` — full OpenAPI 3.1 spec +- `wsgi.py` — gunicorn entrypoint (`from app import create_app`) +- `app/__init__.py` — the Flask app factory: blueprint wiring, JWTManager, CORS, JSON error handlers, `db.create_all()` on boot +- `app/database.py` — the Flask-SQLAlchemy `db` instance +- `app/blueprints/auth_bp.py` — register / login / logout / me, JWT in httpOnly cookies +- `app/models/user.py` — User model with password hashing +- `config.py` — env-driven config that refuses to boot on placeholder secrets +- `docker-compose.yml` + `Dockerfile` — Postgres 16 + gunicorn, healthcheck-gated +- `app/static/index.html` — a single-page register/login/CRUD demo +- `tests/` — pytest + Flask test client +- `.env.example`, `requirements.txt`, `README.md`, `GENOME.json` Per entity: -- `app/models/.py` — SQLAlchemy 2.0 model with `user_id` FK -- `app/schemas/.py` — Pydantic v2 `Base` / `Create` / `Update` / `Response` -- `app/routers/.py` — FastAPI `APIRouter` with full CRUD +- `app/models/.py` — Flask-SQLAlchemy model with a `user_id` FK and `to_dict()` +- `app/blueprints/_bp.py` — full CRUD blueprint, all routes `@jwt_required()`, per-tenant scoped ### Stage 4 — `pack(files) → bytes` @@ -218,4 +249,4 @@ If the former, open a PR. If the latter, it belongs in the full Archiet pipeline MIT. Use it, fork it, learn from it. -The production platform (12+ stacks, compliance packs, quality gates, GitHub push) is commercial: **[archiet.com](https://archiet.com)** +The production platform (9+ stacks, compliance packs, quality gates, GitHub push) is commercial: **[archiet.com](https://archiet.com)** diff --git a/demo.cast b/demo.cast new file mode 100644 index 0000000..cdf0aad --- /dev/null +++ b/demo.cast @@ -0,0 +1,1026 @@ +{"version": 2, "width": 100, "height": 37, "timestamp": 1700000000, "env": {"TERM": "xterm-256color", "SHELL": "/bin/bash"}, "title": "microcodegen.py \u2014 PRD \u2192 running app"} +[0.4, "o", "[32m$[0m "] +[0.4, "o", "["] +[0.415, "o", "9"] +[0.43, "o", "0"] +[0.445, "o", "m"] +[0.46, "o", "#"] +[0.475, "o", " "] +[0.49, "o", "1"] +[0.505, "o", "."] +[0.52, "o", " "] +[0.535, "o", "G"] +[0.55, "o", "e"] +[0.565, "o", "n"] +[0.58, "o", "e"] +[0.595, "o", "r"] +[0.61, "o", "a"] +[0.625, "o", "t"] +[0.64, "o", "e"] +[0.655, "o", " "] +[0.67, "o", "a"] +[0.685, "o", " "] +[0.7, "o", "F"] +[0.715, "o", "l"] +[0.73, "o", "a"] +[0.745, "o", "s"] +[0.76, "o", "k"] +[0.775, "o", " "] +[0.79, "o", "+"] +[0.805, "o", " "] +[0.82, "o", "P"] +[0.835, "o", "o"] +[0.85, "o", "s"] +[0.865, "o", "t"] +[0.88, "o", "g"] +[0.895, "o", "r"] +[0.91, "o", "e"] +[0.925, "o", "s"] +[0.94, "o", " "] +[0.955, "o", "a"] +[0.97, "o", "p"] +[0.985, "o", "p"] +[1.0, "o", " "] +[1.015, "o", "f"] +[1.03, "o", "r"] +[1.045, "o", "o"] +[1.06, "o", "m"] +[1.075, "o", " "] +[1.09, "o", "a"] +[1.105, "o", " "] +[1.12, "o", "p"] +[1.135, "o", "l"] +[1.15, "o", "a"] +[1.165, "o", "i"] +[1.18, "o", "n"] +[1.195, "o", "-"] +[1.21, "o", "E"] +[1.225, "o", "n"] +[1.24, "o", "g"] +[1.255, "o", "l"] +[1.27, "o", "i"] +[1.285, "o", "s"] +[1.3, "o", "h"] +[1.315, "o", " "] +[1.33, "o", "P"] +[1.345, "o", "R"] +[1.36, "o", "D"] +[1.375, "o", "["] +[1.39, "o", "0"] +[1.405, "o", "m"] +[1.42, "o", "\r\n"] +[1.74, "o", "[32m$[0m "] +[1.74, "o", "["] +[1.766, "o", "3"] +[1.792, "o", "6"] +[1.818, "o", "m"] +[1.844, "o", "p"] +[1.87, "o", "y"] +[1.896, "o", "t"] +[1.922, "o", "h"] +[1.948, "o", "o"] +[1.974, "o", "n"] +[2.0, "o", " "] +[2.026, "o", "m"] +[2.052, "o", "i"] +[2.078, "o", "c"] +[2.104, "o", "r"] +[2.13, "o", "o"] +[2.156, "o", "c"] +[2.182, "o", "o"] +[2.208, "o", "d"] +[2.234, "o", "e"] +[2.26, "o", "g"] +[2.286, "o", "e"] +[2.312, "o", "n"] +[2.338, "o", "."] +[2.364, "o", "p"] +[2.39, "o", "y"] +[2.416, "o", " "] +[2.442, "o", "e"] +[2.468, "o", "x"] +[2.494, "o", "a"] +[2.52, "o", "m"] +[2.546, "o", "p"] +[2.572, "o", "l"] +[2.598, "o", "e"] +[2.624, "o", "s"] +[2.65, "o", "/"] +[2.676, "o", "t"] +[2.702, "o", "a"] +[2.728, "o", "s"] +[2.754, "o", "k"] +[2.78, "o", "_"] +[2.806, "o", "m"] +[2.832, "o", "a"] +[2.858, "o", "n"] +[2.884, "o", "a"] +[2.91, "o", "g"] +[2.936, "o", "e"] +[2.962, "o", "r"] +[2.988, "o", "."] +[3.014, "o", "m"] +[3.04, "o", "d"] +[3.066, "o", " "] +[3.092, "o", "-"] +[3.118, "o", "-"] +[3.144, "o", "o"] +[3.17, "o", "u"] +[3.196, "o", "t"] +[3.222, "o", " "] +[3.248, "o", "."] +[3.274, "o", "/"] +[3.3, "o", "m"] +[3.326, "o", "y"] +[3.352, "o", "-"] +[3.378, "o", "t"] +[3.404, "o", "a"] +[3.43, "o", "s"] +[3.456, "o", "k"] +[3.482, "o", "-"] +[3.508, "o", "a"] +[3.534, "o", "p"] +[3.56, "o", "p"] +[3.586, "o", "["] +[3.612, "o", "0"] +[3.638, "o", "m"] +[3.664, "o", "\r\n"] +[3.984, "o", "Wrote 25 files to my-task-app\r\n"] +[4.819, "o", "[32m$[0m "] +[4.819, "o", "["] +[4.834, "o", "9"] +[4.849, "o", "0"] +[4.864, "o", "m"] +[4.879, "o", "#"] +[4.894, "o", " "] +[4.909, "o", "A"] +[4.924, "o", " "] +[4.939, "o", "r"] +[4.954, "o", "e"] +[4.969, "o", "a"] +[4.984, "o", "l"] +[4.999, "o", " "] +[5.014, "o", "a"] +[5.029, "o", "p"] +[5.044, "o", "p"] +[5.059, "o", ","] +[5.074, "o", " "] +[5.089, "o", "n"] +[5.104, "o", "o"] +[5.119, "o", "t"] +[5.134, "o", " "] +[5.149, "o", "a"] +[5.164, "o", "n"] +[5.179, "o", " "] +[5.194, "o", "e"] +[5.209, "o", "m"] +[5.224, "o", "p"] +[5.239, "o", "t"] +[5.254, "o", "y"] +[5.269, "o", " "] +[5.284, "o", "s"] +[5.299, "o", "k"] +[5.314, "o", "e"] +[5.329, "o", "l"] +[5.344, "o", "e"] +[5.359, "o", "t"] +[5.374, "o", "o"] +[5.389, "o", "n"] +[5.404, "o", " "] +[5.419, "o", "—"] +[5.434, "o", " "] +[5.449, "o", "e"] +[5.464, "o", "n"] +[5.479, "o", "t"] +[5.494, "o", "i"] +[5.509, "o", "t"] +[5.524, "o", "y"] +[5.539, "o", "-"] +[5.554, "o", "s"] +[5.569, "o", "p"] +[5.584, "o", "e"] +[5.599, "o", "c"] +[5.614, "o", "i"] +[5.629, "o", "f"] +[5.644, "o", "i"] +[5.659, "o", "c"] +[5.674, "o", " "] +[5.689, "o", "c"] +[5.704, "o", "o"] +[5.719, "o", "d"] +[5.734, "o", "e"] +[5.749, "o", " "] +[5.764, "o", "p"] +[5.779, "o", "e"] +[5.794, "o", "r"] +[5.809, "o", " "] +[5.824, "o", "m"] +[5.839, "o", "o"] +[5.854, "o", "d"] +[5.869, "o", "e"] +[5.884, "o", "l"] +[5.899, "o", ":"] +[5.914, "o", "["] +[5.929, "o", "0"] +[5.944, "o", "m"] +[5.959, "o", "\r\n"] +[6.279, "o", "[32m$[0m "] +[6.279, "o", "["] +[6.305, "o", "3"] +[6.331, "o", "6"] +[6.357, "o", "m"] +[6.383, "o", "t"] +[6.409, "o", "r"] +[6.435, "o", "e"] +[6.461, "o", "e"] +[6.487, "o", " "] +[6.513, "o", "m"] +[6.539, "o", "y"] +[6.565, "o", "-"] +[6.591, "o", "t"] +[6.617, "o", "a"] +[6.643, "o", "s"] +[6.669, "o", "k"] +[6.695, "o", "-"] +[6.721, "o", "a"] +[6.747, "o", "p"] +[6.773, "o", "p"] +[6.799, "o", "["] +[6.825, "o", "0"] +[6.851, "o", "m"] +[6.877, "o", "\r\n"] +[7.197, "o", "[34mmy-task-app/[0m\r\n"] +[7.232, "o", "├─ wsgi.py config.py requirements.txt Dockerfile docker-compose.yml .env.example\r\n"] +[7.267, "o", "├─ README.md GENOME.json [90m# GENOME.json = the architectural IR it rendered from[0m\r\n"] +[7.302, "o", "├─ [34mapp/[0m\r\n"] +[7.337, "o", "│ ├─ __init__.py [90m# Flask app factory: blueprints, JWT, CORS, error handlers[0m\r\n"] +[7.372, "o", "│ ├─ database.py\r\n"] +[7.407, "o", "│ ├─ [34mblueprints/[0m auth_bp project_bp task_bp comment_bp label_bp [90m# CRUD, @jwt_required[0m\r\n"] +[7.442, "o", "│ ├─ [34mmodels/[0m user project task comment label [90m# user_id FK, per-tenant[0m\r\n"] +[7.477, "o", "│ └─ [34mstatic/[0mindex.html [90m# click-through register/login/CRUD page[0m\r\n"] +[7.512, "o", "└─ [34mtests/[0m conftest.py test_health.py\r\n"] +[8.547, "o", "[32m$[0m "] +[8.547, "o", "["] +[8.562, "o", "9"] +[8.577, "o", "0"] +[8.592, "o", "m"] +[8.607, "o", "#"] +[8.622, "o", " "] +[8.637, "o", "2"] +[8.652, "o", "."] +[8.667, "o", " "] +[8.682, "o", "B"] +[8.697, "o", "o"] +[8.712, "o", "o"] +[8.727, "o", "t"] +[8.742, "o", " "] +[8.757, "o", "i"] +[8.772, "o", "t"] +[8.787, "o", " "] +[8.802, "o", "—"] +[8.817, "o", " "] +[8.832, "o", "h"] +[8.847, "o", "e"] +[8.862, "o", "a"] +[8.877, "o", "l"] +[8.892, "o", "t"] +[8.907, "o", "h"] +[8.922, "o", "c"] +[8.937, "o", "h"] +[8.952, "o", "e"] +[8.967, "o", "c"] +[8.982, "o", "k"] +[8.997, "o", "-"] +[9.012, "o", "g"] +[9.027, "o", "a"] +[9.042, "o", "t"] +[9.057, "o", "e"] +[9.072, "o", "d"] +[9.087, "o", ","] +[9.102, "o", " "] +[9.117, "o", "z"] +[9.132, "o", "e"] +[9.147, "o", "r"] +[9.162, "o", "o"] +[9.177, "o", " "] +[9.192, "o", "e"] +[9.207, "o", "d"] +[9.222, "o", "i"] +[9.237, "o", "t"] +[9.252, "o", "s"] +[9.267, "o", ","] +[9.282, "o", " "] +[9.297, "o", "z"] +[9.312, "o", "e"] +[9.327, "o", "r"] +[9.342, "o", "o"] +[9.357, "o", " "] +[9.372, "o", "A"] +[9.387, "o", "P"] +[9.402, "o", "I"] +[9.417, "o", " "] +[9.432, "o", "k"] +[9.447, "o", "e"] +[9.462, "o", "y"] +[9.477, "o", "s"] +[9.492, "o", "["] +[9.507, "o", "0"] +[9.522, "o", "m"] +[9.537, "o", "\r\n"] +[9.857, "o", "[32m$[0m "] +[9.857, "o", "["] +[9.883, "o", "3"] +[9.909, "o", "6"] +[9.935, "o", "m"] +[9.961, "o", "c"] +[9.987, "o", "d"] +[10.013, "o", " "] +[10.039, "o", "m"] +[10.065, "o", "y"] +[10.091, "o", "-"] +[10.117, "o", "t"] +[10.143, "o", "a"] +[10.169, "o", "s"] +[10.195, "o", "k"] +[10.221, "o", "-"] +[10.247, "o", "a"] +[10.273, "o", "p"] +[10.299, "o", "p"] +[10.325, "o", " "] +[10.351, "o", "&"] +[10.377, "o", "&"] +[10.403, "o", " "] +[10.429, "o", "d"] +[10.455, "o", "o"] +[10.481, "o", "c"] +[10.507, "o", "k"] +[10.533, "o", "e"] +[10.559, "o", "r"] +[10.585, "o", " "] +[10.611, "o", "c"] +[10.637, "o", "o"] +[10.663, "o", "m"] +[10.689, "o", "p"] +[10.715, "o", "o"] +[10.741, "o", "s"] +[10.767, "o", "e"] +[10.793, "o", " "] +[10.819, "o", "u"] +[10.845, "o", "p"] +[10.871, "o", " "] +[10.897, "o", "-"] +[10.923, "o", "d"] +[10.949, "o", " "] +[10.975, "o", "-"] +[11.001, "o", "-"] +[11.027, "o", "b"] +[11.053, "o", "u"] +[11.079, "o", "i"] +[11.105, "o", "l"] +[11.131, "o", "d"] +[11.157, "o", "["] +[11.183, "o", "0"] +[11.209, "o", "m"] +[11.235, "o", "\r\n"] +[11.555, "o", "[32m ✔ Container my-task-app-db-1 Healthy[0m\r\n"] +[11.59, "o", "[32m ✔ Container my-task-app-app-1 Started[0m\r\n"] +[12.425, "o", "[32m$[0m "] +[12.425, "o", "["] +[12.44, "o", "9"] +[12.455, "o", "0"] +[12.47, "o", "m"] +[12.485, "o", "#"] +[12.5, "o", " "] +[12.515, "o", "3"] +[12.53, "o", "."] +[12.545, "o", " "] +[12.56, "o", "I"] +[12.575, "o", "t"] +[12.59, "o", "'"] +[12.605, "o", "s"] +[12.62, "o", " "] +[12.635, "o", "l"] +[12.65, "o", "i"] +[12.665, "o", "v"] +[12.68, "o", "e"] +[12.695, "o", "["] +[12.71, "o", "0"] +[12.725, "o", "m"] +[12.74, "o", "\r\n"] +[13.06, "o", "[32m$[0m "] +[13.06, "o", "["] +[13.086, "o", "3"] +[13.112, "o", "6"] +[13.138, "o", "m"] +[13.164, "o", "c"] +[13.19, "o", "u"] +[13.216, "o", "r"] +[13.242, "o", "l"] +[13.268, "o", " "] +[13.294, "o", "l"] +[13.32, "o", "o"] +[13.346, "o", "c"] +[13.372, "o", "a"] +[13.398, "o", "l"] +[13.424, "o", "h"] +[13.45, "o", "o"] +[13.476, "o", "s"] +[13.502, "o", "t"] +[13.528, "o", ":"] +[13.554, "o", "5"] +[13.58, "o", "0"] +[13.606, "o", "0"] +[13.632, "o", "0"] +[13.658, "o", "/"] +[13.684, "o", "a"] +[13.71, "o", "p"] +[13.736, "o", "i"] +[13.762, "o", "/"] +[13.788, "o", "h"] +[13.814, "o", "e"] +[13.84, "o", "a"] +[13.866, "o", "l"] +[13.892, "o", "t"] +[13.918, "o", "h"] +[13.944, "o", "["] +[13.97, "o", "0"] +[13.996, "o", "m"] +[14.022, "o", "\r\n"] +[14.342, "o", "{\"status\":\"ok\",\"version\":\"task_manager_saa_s\"}\r\n"] +[15.177, "o", "[32m$[0m "] +[15.177, "o", "["] +[15.192, "o", "9"] +[15.207, "o", "0"] +[15.222, "o", "m"] +[15.237, "o", "#"] +[15.252, "o", " "] +[15.267, "o", "R"] +[15.282, "o", "e"] +[15.297, "o", "g"] +[15.312, "o", "i"] +[15.327, "o", "s"] +[15.342, "o", "t"] +[15.357, "o", "e"] +[15.372, "o", "r"] +[15.387, "o", " "] +[15.402, "o", "—"] +[15.417, "o", " "] +[15.432, "o", "i"] +[15.447, "o", "s"] +[15.462, "o", "s"] +[15.477, "o", "u"] +[15.492, "o", "e"] +[15.507, "o", "s"] +[15.522, "o", " "] +[15.537, "o", "a"] +[15.552, "o", " "] +[15.567, "o", "J"] +[15.582, "o", "W"] +[15.597, "o", "T"] +[15.612, "o", " "] +[15.627, "o", "i"] +[15.642, "o", "n"] +[15.657, "o", " "] +[15.672, "o", "a"] +[15.687, "o", "n"] +[15.702, "o", " "] +[15.717, "o", "h"] +[15.732, "o", "t"] +[15.747, "o", "t"] +[15.762, "o", "p"] +[15.777, "o", "O"] +[15.792, "o", "n"] +[15.807, "o", "l"] +[15.822, "o", "y"] +[15.837, "o", " "] +[15.852, "o", "c"] +[15.867, "o", "o"] +[15.882, "o", "o"] +[15.897, "o", "k"] +[15.912, "o", "i"] +[15.927, "o", "e"] +[15.942, "o", " "] +[15.957, "o", "("] +[15.972, "o", "n"] +[15.987, "o", "e"] +[16.002, "o", "v"] +[16.017, "o", "e"] +[16.032, "o", "r"] +[16.047, "o", " "] +[16.062, "o", "l"] +[16.077, "o", "o"] +[16.092, "o", "c"] +[16.107, "o", "a"] +[16.122, "o", "l"] +[16.137, "o", "S"] +[16.152, "o", "t"] +[16.167, "o", "o"] +[16.182, "o", "r"] +[16.197, "o", "a"] +[16.212, "o", "g"] +[16.227, "o", "e"] +[16.242, "o", ")"] +[16.257, "o", "["] +[16.272, "o", "0"] +[16.287, "o", "m"] +[16.302, "o", "\r\n"] +[16.622, "o", "[32m$[0m "] +[16.622, "o", "["] +[16.648, "o", "3"] +[16.674, "o", "6"] +[16.7, "o", "m"] +[16.726, "o", "c"] +[16.752, "o", "u"] +[16.778, "o", "r"] +[16.804, "o", "l"] +[16.83, "o", " "] +[16.856, "o", "-"] +[16.882, "o", "c"] +[16.908, "o", " "] +[16.934, "o", "c"] +[16.96, "o", "o"] +[16.986, "o", "o"] +[17.012, "o", "k"] +[17.038, "o", "i"] +[17.064, "o", "e"] +[17.09, "o", "s"] +[17.116, "o", "."] +[17.142, "o", "t"] +[17.168, "o", "x"] +[17.194, "o", "t"] +[17.22, "o", " "] +[17.246, "o", "-"] +[17.272, "o", "X"] +[17.298, "o", " "] +[17.324, "o", "P"] +[17.35, "o", "O"] +[17.376, "o", "S"] +[17.402, "o", "T"] +[17.428, "o", " "] +[17.454, "o", "l"] +[17.48, "o", "o"] +[17.506, "o", "c"] +[17.532, "o", "a"] +[17.558, "o", "l"] +[17.584, "o", "h"] +[17.61, "o", "o"] +[17.636, "o", "s"] +[17.662, "o", "t"] +[17.688, "o", ":"] +[17.714, "o", "5"] +[17.74, "o", "0"] +[17.766, "o", "0"] +[17.792, "o", "0"] +[17.818, "o", "/"] +[17.844, "o", "a"] +[17.87, "o", "p"] +[17.896, "o", "i"] +[17.922, "o", "/"] +[17.948, "o", "a"] +[17.974, "o", "u"] +[18.0, "o", "t"] +[18.026, "o", "h"] +[18.052, "o", "/"] +[18.078, "o", "r"] +[18.104, "o", "e"] +[18.13, "o", "g"] +[18.156, "o", "i"] +[18.182, "o", "s"] +[18.208, "o", "t"] +[18.234, "o", "e"] +[18.26, "o", "r"] +[18.286, "o", " "] +[18.312, "o", "\\"] +[18.338, "o", "["] +[18.364, "o", "0"] +[18.39, "o", "m"] +[18.416, "o", "\r\n"] +[18.736, "o", "["] +[18.762, "o", "3"] +[18.788, "o", "6"] +[18.814, "o", "m"] +[18.84, "o", " "] +[18.866, "o", " "] +[18.892, "o", " "] +[18.918, "o", " "] +[18.944, "o", " "] +[18.97, "o", "-"] +[18.996, "o", "d"] +[19.022, "o", " "] +[19.048, "o", "'"] +[19.074, "o", "{"] +[19.1, "o", "\""] +[19.126, "o", "e"] +[19.152, "o", "m"] +[19.178, "o", "a"] +[19.204, "o", "i"] +[19.23, "o", "l"] +[19.256, "o", "\""] +[19.282, "o", ":"] +[19.308, "o", "\""] +[19.334, "o", "y"] +[19.36, "o", "o"] +[19.386, "o", "u"] +[19.412, "o", "@"] +[19.438, "o", "e"] +[19.464, "o", "x"] +[19.49, "o", "a"] +[19.516, "o", "m"] +[19.542, "o", "p"] +[19.568, "o", "l"] +[19.594, "o", "e"] +[19.62, "o", "."] +[19.646, "o", "c"] +[19.672, "o", "o"] +[19.698, "o", "m"] +[19.724, "o", "\""] +[19.75, "o", ","] +[19.776, "o", "\""] +[19.802, "o", "p"] +[19.828, "o", "a"] +[19.854, "o", "s"] +[19.88, "o", "s"] +[19.906, "o", "w"] +[19.932, "o", "o"] +[19.958, "o", "r"] +[19.984, "o", "d"] +[20.01, "o", "\""] +[20.036, "o", ":"] +[20.062, "o", "\""] +[20.088, "o", "h"] +[20.114, "o", "u"] +[20.14, "o", "n"] +[20.166, "o", "t"] +[20.192, "o", "e"] +[20.218, "o", "r"] +[20.244, "o", "2"] +[20.27, "o", "2"] +[20.296, "o", "h"] +[20.322, "o", "u"] +[20.348, "o", "n"] +[20.374, "o", "t"] +[20.4, "o", "e"] +[20.426, "o", "r"] +[20.452, "o", "\""] +[20.478, "o", "}"] +[20.504, "o", "'"] +[20.53, "o", "["] +[20.556, "o", "0"] +[20.582, "o", "m"] +[20.608, "o", "\r\n"] +[20.928, "o", "{\"user\":{\"email\":\"you@example.com\",\"id\":\"c3f365ce-dd75-47c1-a26b-9b0fe928369c\"}}\r\n"] +[21.763, "o", "[32m$[0m "] +[21.763, "o", "["] +[21.778, "o", "9"] +[21.793, "o", "0"] +[21.808, "o", "m"] +[21.823, "o", "#"] +[21.838, "o", " "] +[21.853, "o", "C"] +[21.868, "o", "r"] +[21.883, "o", "e"] +[21.898, "o", "a"] +[21.913, "o", "t"] +[21.928, "o", "e"] +[21.943, "o", " "] +[21.958, "o", "a"] +[21.973, "o", " "] +[21.988, "o", "p"] +[22.003, "o", "r"] +[22.018, "o", "o"] +[22.033, "o", "j"] +[22.048, "o", "e"] +[22.063, "o", "c"] +[22.078, "o", "t"] +[22.093, "o", " "] +[22.108, "o", "—"] +[22.123, "o", " "] +[22.138, "o", "a"] +[22.153, "o", "u"] +[22.168, "o", "t"] +[22.183, "o", "h"] +[22.198, "o", " "] +[22.213, "o", "r"] +[22.228, "o", "e"] +[22.243, "o", "q"] +[22.258, "o", "u"] +[22.273, "o", "i"] +[22.288, "o", "r"] +[22.303, "o", "e"] +[22.318, "o", "d"] +[22.333, "o", ","] +[22.348, "o", " "] +[22.363, "o", "r"] +[22.378, "o", "o"] +[22.393, "o", "w"] +[22.408, "o", " "] +[22.423, "o", "s"] +[22.438, "o", "c"] +[22.453, "o", "o"] +[22.468, "o", "p"] +[22.483, "o", "e"] +[22.498, "o", "d"] +[22.513, "o", " "] +[22.528, "o", "t"] +[22.543, "o", "o"] +[22.558, "o", " "] +[22.573, "o", "t"] +[22.588, "o", "h"] +[22.603, "o", "i"] +[22.618, "o", "s"] +[22.633, "o", " "] +[22.648, "o", "u"] +[22.663, "o", "s"] +[22.678, "o", "e"] +[22.693, "o", "r"] +[22.708, "o", "["] +[22.723, "o", "0"] +[22.738, "o", "m"] +[22.753, "o", "\r\n"] +[23.073, "o", "[32m$[0m "] +[23.073, "o", "["] +[23.099, "o", "3"] +[23.125, "o", "6"] +[23.151, "o", "m"] +[23.177, "o", "c"] +[23.203, "o", "u"] +[23.229, "o", "r"] +[23.255, "o", "l"] +[23.281, "o", " "] +[23.307, "o", "-"] +[23.333, "o", "b"] +[23.359, "o", " "] +[23.385, "o", "c"] +[23.411, "o", "o"] +[23.437, "o", "o"] +[23.463, "o", "k"] +[23.489, "o", "i"] +[23.515, "o", "e"] +[23.541, "o", "s"] +[23.567, "o", "."] +[23.593, "o", "t"] +[23.619, "o", "x"] +[23.645, "o", "t"] +[23.671, "o", " "] +[23.697, "o", "-"] +[23.723, "o", "X"] +[23.749, "o", " "] +[23.775, "o", "P"] +[23.801, "o", "O"] +[23.827, "o", "S"] +[23.853, "o", "T"] +[23.879, "o", " "] +[23.905, "o", "l"] +[23.931, "o", "o"] +[23.957, "o", "c"] +[23.983, "o", "a"] +[24.009, "o", "l"] +[24.035, "o", "h"] +[24.061, "o", "o"] +[24.087, "o", "s"] +[24.113, "o", "t"] +[24.139, "o", ":"] +[24.165, "o", "5"] +[24.191, "o", "0"] +[24.217, "o", "0"] +[24.243, "o", "0"] +[24.269, "o", "/"] +[24.295, "o", "a"] +[24.321, "o", "p"] +[24.347, "o", "i"] +[24.373, "o", "/"] +[24.399, "o", "p"] +[24.425, "o", "r"] +[24.451, "o", "o"] +[24.477, "o", "j"] +[24.503, "o", "e"] +[24.529, "o", "c"] +[24.555, "o", "t"] +[24.581, "o", "s"] +[24.607, "o", "/"] +[24.633, "o", " "] +[24.659, "o", "-"] +[24.685, "o", "d"] +[24.711, "o", " "] +[24.737, "o", "'"] +[24.763, "o", "{"] +[24.789, "o", "\""] +[24.815, "o", "n"] +[24.841, "o", "a"] +[24.867, "o", "m"] +[24.893, "o", "e"] +[24.919, "o", "\""] +[24.945, "o", ":"] +[24.971, "o", "\""] +[24.997, "o", "M"] +[25.023, "o", "y"] +[25.049, "o", " "] +[25.075, "o", "f"] +[25.101, "o", "i"] +[25.127, "o", "r"] +[25.153, "o", "s"] +[25.179, "o", "t"] +[25.205, "o", " "] +[25.231, "o", "p"] +[25.257, "o", "r"] +[25.283, "o", "o"] +[25.309, "o", "j"] +[25.335, "o", "e"] +[25.361, "o", "c"] +[25.387, "o", "t"] +[25.413, "o", "\""] +[25.439, "o", "}"] +[25.465, "o", "'"] +[25.491, "o", "["] +[25.517, "o", "0"] +[25.543, "o", "m"] +[25.569, "o", "\r\n"] +[25.889, "o", "{\"id\":\"d2d14b5c-8026-421a-b027-cdc0b6c5ae63\",\"name\":\"My first project\",\r\n"] +[25.924, "o", " \"user_id\":\"c3f365ce-dd75-47c1-a26b-9b0fe928369c\",\"status\":null}\r\n"] +[26.759, "o", "[32m$[0m "] +[26.759, "o", "["] +[26.774, "o", "9"] +[26.789, "o", "0"] +[26.804, "o", "m"] +[26.819, "o", "#"] +[26.834, "o", " "] +[26.849, "o", "L"] +[26.864, "o", "i"] +[26.879, "o", "s"] +[26.894, "o", "t"] +[26.909, "o", " "] +[26.924, "o", "—"] +[26.939, "o", " "] +[26.954, "o", "r"] +[26.969, "o", "e"] +[26.984, "o", "t"] +[26.999, "o", "u"] +[27.014, "o", "r"] +[27.029, "o", "n"] +[27.044, "o", "s"] +[27.059, "o", " "] +[27.074, "o", "o"] +[27.089, "o", "n"] +[27.104, "o", "l"] +[27.119, "o", "y"] +[27.134, "o", " "] +[27.149, "o", "y"] +[27.164, "o", "o"] +[27.179, "o", "u"] +[27.194, "o", "r"] +[27.209, "o", " "] +[27.224, "o", "r"] +[27.239, "o", "o"] +[27.254, "o", "w"] +[27.269, "o", "s"] +[27.284, "o", "["] +[27.299, "o", "0"] +[27.314, "o", "m"] +[27.329, "o", "\r\n"] +[27.649, "o", "[32m$[0m "] +[27.649, "o", "["] +[27.675, "o", "3"] +[27.701, "o", "6"] +[27.727, "o", "m"] +[27.753, "o", "c"] +[27.779, "o", "u"] +[27.805, "o", "r"] +[27.831, "o", "l"] +[27.857, "o", " "] +[27.883, "o", "-"] +[27.909, "o", "b"] +[27.935, "o", " "] +[27.961, "o", "c"] +[27.987, "o", "o"] +[28.013, "o", "o"] +[28.039, "o", "k"] +[28.065, "o", "i"] +[28.091, "o", "e"] +[28.117, "o", "s"] +[28.143, "o", "."] +[28.169, "o", "t"] +[28.195, "o", "x"] +[28.221, "o", "t"] +[28.247, "o", " "] +[28.273, "o", "l"] +[28.299, "o", "o"] +[28.325, "o", "c"] +[28.351, "o", "a"] +[28.377, "o", "l"] +[28.403, "o", "h"] +[28.429, "o", "o"] +[28.455, "o", "s"] +[28.481, "o", "t"] +[28.507, "o", ":"] +[28.533, "o", "5"] +[28.559, "o", "0"] +[28.585, "o", "0"] +[28.611, "o", "0"] +[28.637, "o", "/"] +[28.663, "o", "a"] +[28.689, "o", "p"] +[28.715, "o", "i"] +[28.741, "o", "/"] +[28.767, "o", "p"] +[28.793, "o", "r"] +[28.819, "o", "o"] +[28.845, "o", "j"] +[28.871, "o", "e"] +[28.897, "o", "c"] +[28.923, "o", "t"] +[28.949, "o", "s"] +[28.975, "o", "/"] +[29.001, "o", "["] +[29.027, "o", "0"] +[29.053, "o", "m"] +[29.079, "o", "\r\n"] +[29.399, "o", "[{\"id\":\"d2d14b5c-...\",\"name\":\"My first project\",\"user_id\":\"c3f365ce-...\"}]\r\n"] +[30.234, "o", "[32m$[0m "] +[30.234, "o", "["] +[30.249, "o", "9"] +[30.264, "o", "0"] +[30.279, "o", "m"] +[30.294, "o", "#"] +[30.309, "o", " "] +[30.324, "o", "W"] +[30.339, "o", "i"] +[30.354, "o", "t"] +[30.369, "o", "h"] +[30.384, "o", "o"] +[30.399, "o", "u"] +[30.414, "o", "t"] +[30.429, "o", " "] +[30.444, "o", "t"] +[30.459, "o", "h"] +[30.474, "o", "e"] +[30.489, "o", " "] +[30.504, "o", "c"] +[30.519, "o", "o"] +[30.534, "o", "o"] +[30.549, "o", "k"] +[30.564, "o", "i"] +[30.579, "o", "e"] +[30.594, "o", ","] +[30.609, "o", " "] +[30.624, "o", "t"] +[30.639, "o", "h"] +[30.654, "o", "e"] +[30.669, "o", " "] +[30.684, "o", "A"] +[30.699, "o", "P"] +[30.714, "o", "I"] +[30.729, "o", " "] +[30.744, "o", "r"] +[30.759, "o", "e"] +[30.774, "o", "f"] +[30.789, "o", "u"] +[30.804, "o", "s"] +[30.819, "o", "e"] +[30.834, "o", "s"] +[30.849, "o", "["] +[30.864, "o", "0"] +[30.879, "o", "m"] +[30.894, "o", "\r\n"] +[31.214, "o", "[32m$[0m "] +[31.214, "o", "["] +[31.24, "o", "3"] +[31.266, "o", "6"] +[31.292, "o", "m"] +[31.318, "o", "c"] +[31.344, "o", "u"] +[31.37, "o", "r"] +[31.396, "o", "l"] +[31.422, "o", " "] +[31.448, "o", "l"] +[31.474, "o", "o"] +[31.5, "o", "c"] +[31.526, "o", "a"] +[31.552, "o", "l"] +[31.578, "o", "h"] +[31.604, "o", "o"] +[31.63, "o", "s"] +[31.656, "o", "t"] +[31.682, "o", ":"] +[31.708, "o", "5"] +[31.734, "o", "0"] +[31.76, "o", "0"] +[31.786, "o", "0"] +[31.812, "o", "/"] +[31.838, "o", "a"] +[31.864, "o", "p"] +[31.89, "o", "i"] +[31.916, "o", "/"] +[31.942, "o", "p"] +[31.968, "o", "r"] +[31.994, "o", "o"] +[32.02, "o", "j"] +[32.046, "o", "e"] +[32.072, "o", "c"] +[32.098, "o", "t"] +[32.124, "o", "s"] +[32.15, "o", "/"] +[32.176, "o", "["] +[32.202, "o", "0"] +[32.228, "o", "m"] +[32.254, "o", "\r\n"] +[32.574, "o", "[33m{\"msg\":\"Missing cookie \\\"access_token_cookie\\\"\"}[0m\r\n"] diff --git a/demo.sh b/demo.sh new file mode 100644 index 0000000..ee3067b --- /dev/null +++ b/demo.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +# +# microcodegen demo — PRD text → a running Flask app, end to end. +# +# Requires: python 3.10+, docker (for the Postgres-backed boot), curl. +# Usage: ./demo.sh [path/to/prd.md] (defaults to examples/task_manager.md) +# +set -euo pipefail + +PRD="${1:-examples/task_manager.md}" +OUT="./my-task-app" + +echo "# 1. Generate a Flask + Postgres app from a plain-English PRD" +python microcodegen.py "$PRD" --out "$OUT" + +echo +echo "# 2. Boot it — Flask + Postgres, healthcheck-gated, zero edits, zero API keys" +cd "$OUT" +[ -f .env ] || cp .env.example .env +docker compose up -d --build + +echo +echo "# waiting for the app to come up..." +until curl -fs http://localhost:5000/api/health >/dev/null; do sleep 1; done + +echo +echo "# 3. It's live" +echo "\$ curl localhost:5000/api/health" +curl -s http://localhost:5000/api/health; echo + +echo +echo "# Register — issues a JWT in an httpOnly cookie (never localStorage)" +curl -s -c cookies.txt -X POST http://localhost:5000/api/auth/register \ + -H 'Content-Type: application/json' \ + -d '{"email":"you@example.com","password":"hunter22hunter"}'; echo + +echo +echo "# Create a project — auth required, row scoped to this user" +curl -s -b cookies.txt -X POST http://localhost:5000/api/projects/ \ + -H 'Content-Type: application/json' \ + -d '{"name":"My first project"}'; echo + +echo +echo "# List — returns only your rows" +curl -s -b cookies.txt http://localhost:5000/api/projects/; echo + +echo +echo "# Without the cookie, the API refuses" +curl -s http://localhost:5000/api/projects/; echo + +echo +echo "# Done. Open http://localhost:5000 for the click-through demo page." +echo "# Tear down with: cd $OUT && docker compose down -v" diff --git a/demo.svg b/demo.svg new file mode 100644 index 0000000..450eba6 --- /dev/null +++ b/demo.svg @@ -0,0 +1 @@ +[32m$[0m[32m$[0m[[32m$[0m[9[32m$[0m[90[32m$[0m[90m[32m$[0m[90m#[32m$[0m[90m#1.[32m$[0m[90m#1.Generate[32m$[0m[90m#1.Generatea[32m$[0m[90m#1.GenerateaFlask[32m$[0m[90m#1.GenerateaFlask+[32m$[0m[90m#1.GenerateaFlask+Postgres[32m$[0m[90m#1.GenerateaFlask+Postgresapp[32m$[0m[90m#1.GenerateaFlask+Postgresappfrom[32m$[0m[90m#1.GenerateaFlask+Postgresappfroma[32m$[0m[90m#1.GenerateaFlask+Postgresappfromaplain-English[32m$[0m[90m#1.GenerateaFlask+Postgresappfromaplain-EnglishPRD[0m[32m$[0m[3[32m$[0m[36[32m$[0m[36m[32m$[0m[36mpython[32m$[0m[36mpythonmicrocodegen.py[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--out[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--out./my-task-app[0mWrote25filestomy-task-app[32m$[0m[90m#A[32m$[0m[90m#Areal[32m$[0m[90m#Arealapp,[32m$[0m[90m#Arealapp,not[32m$[0m[90m#Arealapp,notan[32m$[0m[90m#Arealapp,notanempty[32m$[0m[90m#Arealapp,notanemptyskeleton[32m$[0m[90m#Arealapp,notanemptyskeleton[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specific[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specificcode[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specificcodeper[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specificcodepermodel:[0m[32m$[0m[36mtree[32m$[0m[36mtreemy-task-app[0m[34mmy-task-app/[0m├─wsgi.pyconfig.pyrequirements.txtDockerfiledocker-compose.yml.env.example├─README.mdGENOME.json[90m#GENOME.json=thearchitecturalIRitrenderedfrom[0m├─[34mapp/[0m├─__init__.py[90m#Flaskappfactory:blueprints,JWT,CORS,errorhandlers[0m├─database.py├─[34mblueprints/[0mauth_bpproject_bptask_bpcomment_bplabel_bp[90m#CRUD,@jwt_required[0m├─[34mmodels/[0muserprojecttaskcommentlabel[90m#user_idFK,per-tenant[0m└─[34mstatic/[0mindex.html[90m#click-throughregister/login/CRUDpage[0m└─[34mtests/[0mconftest.pytest_health.py[32m$[0m[90m#2.[32m$[0m[90m#2.Boot[32m$[0m[90m#2.Bootit[32m$[0m[90m#2.Bootit[32m$[0m[90m#2.Bootithealthcheck-gated,[32m$[0m[90m#2.Bootithealthcheck-gated,zero[32m$[0m[90m#2.Bootithealthcheck-gated,zeroedits,[32m$[0m[90m#2.Bootithealthcheck-gated,zeroedits,zero[32m$[0m[90m#2.Bootithealthcheck-gated,zeroedits,zeroAPI[32m$[0m[90m#2.Bootithealthcheck-gated,zeroedits,zeroAPIkeys[0m[32m$[0m[36mc[32m$[0m[36mcd[32m$[0m[36mcdmy-task-app[32m$[0m[36mcdmy-task-app&&[32m$[0m[36mcdmy-task-app&&docker[32m$[0m[36mcdmy-task-app&&dockercompose[32m$[0m[36mcdmy-task-app&&dockercomposeup[32m$[0m[36mcdmy-task-app&&dockercomposeup-d[32m$[0m[36mcdmy-task-app&&dockercomposeup-d--build[0m[32mContainermy-task-app-db-1Healthy[0m[32mContainermy-task-app-app-1Started[0m[32m$[0m[90m#3.[32m$[0m[90m#3.It's[32m$[0m[90m#3.It'slive[0m[32m$[0m[36mcu[32m$[0m[36mcur[32m$[0m[36mcurl[32m$[0m[36mcurll[32m$[0m[36mcurllo[32m$[0m[36mcurlloc[32m$[0m[36mcurlloca[32m$[0m[36mcurllocal[32m$[0m[36mcurllocalh[32m$[0m[36mcurllocalho[32m$[0m[36mcurllocalhos[32m$[0m[36mcurllocalhost[32m$[0m[36mcurllocalhost:[32m$[0m[36mcurllocalhost:5[32m$[0m[36mcurllocalhost:50[32m$[0m[36mcurllocalhost:500[32m$[0m[36mcurllocalhost:5000[32m$[0m[36mcurllocalhost:5000/[32m$[0m[36mcurllocalhost:5000/a[32m$[0m[36mcurllocalhost:5000/ap[32m$[0m[36mcurllocalhost:5000/api[32m$[0m[36mcurllocalhost:5000/api/[32m$[0m[36mcurllocalhost:5000/api/health[0m{"status":"ok","version":"task_manager_saa_s"}[32m$[0m[90m#Register[32m$[0m[90m#Register[32m$[0m[90m#Registerissues[32m$[0m[90m#Registerissuesa[32m$[0m[90m#RegisterissuesaJWT[32m$[0m[90m#RegisterissuesaJWTin[32m$[0m[90m#RegisterissuesaJWTinan[32m$[0m[90m#RegisterissuesaJWTinanhttpOnly[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(never[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(neverlocalStorage)[0m[32m$[0m[36mcurl-[32m$[0m[36mcurl-c[32m$[0m[36mcurl-ccookies.txt[32m$[0m[36mcurl-ccookies.txt-X[32m$[0m[36mcurl-ccookies.txt-XPOST[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api/auth/register[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api/auth/register\[0m[36m[36m-d[36m-d'{"email":"you@example.com","password":"hunter22hunter"}'[0m{"user":{"email":"you@example.com","id":"c3f365ce-dd75-47c1-a26b-9b0fe928369c"}}[32m$[0m[90m#Create[32m$[0m[90m#Createa[32m$[0m[90m#Createaproject[32m$[0m[90m#Createaproject[32m$[0m[90m#Createaprojectauth[32m$[0m[90m#Createaprojectauthrequired,[32m$[0m[90m#Createaprojectauthrequired,row[32m$[0m[90m#Createaprojectauthrequired,rowscoped[32m$[0m[90m#Createaprojectauthrequired,rowscopedto[32m$[0m[90m#Createaprojectauthrequired,rowscopedtothis[32m$[0m[90m#Createaprojectauthrequired,rowscopedtothisuser[0m[32m$[0m[36mcurl-b[32m$[0m[36mcurl-bc[32m$[0m[36mcurl-bco[32m$[0m[36mcurl-bcoo[32m$[0m[36mcurl-bcook[32m$[0m[36mcurl-bcooki[32m$[0m[36mcurl-bcookie[32m$[0m[36mcurl-bcookies[32m$[0m[36mcurl-bcookies.[32m$[0m[36mcurl-bcookies.t[32m$[0m[36mcurl-bcookies.tx[32m$[0m[36mcurl-bcookies.txt[32m$[0m[36mcurl-bcookies.txt-X[32m$[0m[36mcurl-bcookies.txt-XPOST[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name":"My[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name":"Myfirst[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name":"Myfirstproject"}'[0m{"id":"d2d14b5c-8026-421a-b027-cdc0b6c5ae63","name":"Myfirstproject","user_id":"c3f365ce-dd75-47c1-a26b-9b0fe928369c","status":null}[32m$[0m[90m#List[32m$[0m[90m#List[32m$[0m[90m#Listreturns[32m$[0m[90m#Listreturnsonly[32m$[0m[90m#Listreturnsonlyyour[32m$[0m[90m#Listreturnsonlyyourrows[0m[32m$[0m[36mcurl-bcookies.txtlocalhost:5000/api/projects/[0m[{"id":"d2d14b5c-...","name":"Myfirstproject","user_id":"c3f365ce-..."}][32m$[0m[90m#Without[32m$[0m[90m#Withoutthe[32m$[0m[90m#Withoutthecookie,[32m$[0m[90m#Withoutthecookie,the[32m$[0m[90m#Withoutthecookie,theAPI[32m$[0m[90m#Withoutthecookie,theAPIrefuses[0m[32m$[0m[36mcurllocalhost:5000/api/projects/[0m[32m$[0m[90m#1[32m$[0m[90m#1.G[32m$[0m[90m#1.Ge[32m$[0m[90m#1.Gen[32m$[0m[90m#1.Gene[32m$[0m[90m#1.Gener[32m$[0m[90m#1.Genera[32m$[0m[90m#1.Generat[32m$[0m[90m#1.GenerateaF[32m$[0m[90m#1.GenerateaFl[32m$[0m[90m#1.GenerateaFla[32m$[0m[90m#1.GenerateaFlas[32m$[0m[90m#1.GenerateaFlask+P[32m$[0m[90m#1.GenerateaFlask+Po[32m$[0m[90m#1.GenerateaFlask+Pos[32m$[0m[90m#1.GenerateaFlask+Post[32m$[0m[90m#1.GenerateaFlask+Postg[32m$[0m[90m#1.GenerateaFlask+Postgr[32m$[0m[90m#1.GenerateaFlask+Postgre[32m$[0m[90m#1.GenerateaFlask+Postgresa[32m$[0m[90m#1.GenerateaFlask+Postgresap[32m$[0m[90m#1.GenerateaFlask+Postgresappf[32m$[0m[90m#1.GenerateaFlask+Postgresappfr[32m$[0m[90m#1.GenerateaFlask+Postgresappfro[32m$[0m[90m#1.GenerateaFlask+Postgresappfromap[32m$[0m[90m#1.GenerateaFlask+Postgresappfromapl[32m$[0m[90m#1.GenerateaFlask+Postgresappfromapla[32m$[0m[90m#1.GenerateaFlask+Postgresappfromaplai[32m$[0m[90m#1.GenerateaFlask+Postgresappfromaplain[32m$[0m[90m#1.GenerateaFlask+Postgresappfromaplain-[32m$[0m[90m#1.GenerateaFlask+Postgresappfromaplain-E[32m$[0m[90m#1.GenerateaFlask+Postgresappfromaplain-En[32m$[0m[90m#1.GenerateaFlask+Postgresappfromaplain-Eng[32m$[0m[90m#1.GenerateaFlask+Postgresappfromaplain-Engl[32m$[0m[90m#1.GenerateaFlask+Postgresappfromaplain-Engli[32m$[0m[90m#1.GenerateaFlask+Postgresappfromaplain-Englis[32m$[0m[90m#1.GenerateaFlask+Postgresappfromaplain-EnglishP[32m$[0m[90m#1.GenerateaFlask+Postgresappfromaplain-EnglishPR[32m$[0m[90m#1.GenerateaFlask+Postgresappfromaplain-EnglishPRD[32m$[0m[90m#1.GenerateaFlask+Postgresappfromaplain-EnglishPRD[[32m$[0m[90m#1.GenerateaFlask+Postgresappfromaplain-EnglishPRD[0[32m$[0m[36mp[32m$[0m[36mpy[32m$[0m[36mpyt[32m$[0m[36mpyth[32m$[0m[36mpytho[32m$[0m[36mpythonm[32m$[0m[36mpythonmi[32m$[0m[36mpythonmic[32m$[0m[36mpythonmicr[32m$[0m[36mpythonmicro[32m$[0m[36mpythonmicroc[32m$[0m[36mpythonmicroco[32m$[0m[36mpythonmicrocod[32m$[0m[36mpythonmicrocode[32m$[0m[36mpythonmicrocodeg[32m$[0m[36mpythonmicrocodege[32m$[0m[36mpythonmicrocodegen[32m$[0m[36mpythonmicrocodegen.[32m$[0m[36mpythonmicrocodegen.p[32m$[0m[36mpythonmicrocodegen.pye[32m$[0m[36mpythonmicrocodegen.pyex[32m$[0m[36mpythonmicrocodegen.pyexa[32m$[0m[36mpythonmicrocodegen.pyexam[32m$[0m[36mpythonmicrocodegen.pyexamp[32m$[0m[36mpythonmicrocodegen.pyexampl[32m$[0m[36mpythonmicrocodegen.pyexample[32m$[0m[36mpythonmicrocodegen.pyexamples[32m$[0m[36mpythonmicrocodegen.pyexamples/[32m$[0m[36mpythonmicrocodegen.pyexamples/t[32m$[0m[36mpythonmicrocodegen.pyexamples/ta[32m$[0m[36mpythonmicrocodegen.pyexamples/tas[32m$[0m[36mpythonmicrocodegen.pyexamples/task[32m$[0m[36mpythonmicrocodegen.pyexamples/task_[32m$[0m[36mpythonmicrocodegen.pyexamples/task_m[32m$[0m[36mpythonmicrocodegen.pyexamples/task_ma[32m$[0m[36mpythonmicrocodegen.pyexamples/task_man[32m$[0m[36mpythonmicrocodegen.pyexamples/task_mana[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manag[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manage[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.m[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md-[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--o[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--ou[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--out.[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--out./[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--out./m[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--out./my[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--out./my-[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--out./my-t[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--out./my-ta[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--out./my-tas[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--out./my-task[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--out./my-task-[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--out./my-task-a[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--out./my-task-ap[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--out./my-task-app[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--out./my-task-app[[32m$[0m[36mpythonmicrocodegen.pyexamples/task_manager.md--out./my-task-app[0[32m$[0m[90m#Ar[32m$[0m[90m#Are[32m$[0m[90m#Area[32m$[0m[90m#Areala[32m$[0m[90m#Arealap[32m$[0m[90m#Arealapp[32m$[0m[90m#Arealapp,n[32m$[0m[90m#Arealapp,no[32m$[0m[90m#Arealapp,nota[32m$[0m[90m#Arealapp,notane[32m$[0m[90m#Arealapp,notanem[32m$[0m[90m#Arealapp,notanemp[32m$[0m[90m#Arealapp,notanempt[32m$[0m[90m#Arealapp,notanemptys[32m$[0m[90m#Arealapp,notanemptysk[32m$[0m[90m#Arealapp,notanemptyske[32m$[0m[90m#Arealapp,notanemptyskel[32m$[0m[90m#Arealapp,notanemptyskele[32m$[0m[90m#Arealapp,notanemptyskelet[32m$[0m[90m#Arealapp,notanemptyskeleto[32m$[0m[90m#Arealapp,notanemptyskeletone[32m$[0m[90m#Arealapp,notanemptyskeletonen[32m$[0m[90m#Arealapp,notanemptyskeletonent[32m$[0m[90m#Arealapp,notanemptyskeletonenti[32m$[0m[90m#Arealapp,notanemptyskeletonentit[32m$[0m[90m#Arealapp,notanemptyskeletonentity[32m$[0m[90m#Arealapp,notanemptyskeletonentity-[32m$[0m[90m#Arealapp,notanemptyskeletonentity-s[32m$[0m[90m#Arealapp,notanemptyskeletonentity-sp[32m$[0m[90m#Arealapp,notanemptyskeletonentity-spe[32m$[0m[90m#Arealapp,notanemptyskeletonentity-spec[32m$[0m[90m#Arealapp,notanemptyskeletonentity-speci[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specif[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specifi[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specificc[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specificco[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specificcod[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specificcodep[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specificcodepe[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specificcodeperm[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specificcodepermo[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specificcodepermod[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specificcodepermode[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specificcodepermodel[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specificcodepermodel:[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specificcodepermodel:[[32m$[0m[90m#Arealapp,notanemptyskeletonentity-specificcodepermodel:[0[32m$[0m[36mt[32m$[0m[36mtr[32m$[0m[36mtre[32m$[0m[36mtreem[32m$[0m[36mtreemy[32m$[0m[36mtreemy-[32m$[0m[36mtreemy-t[32m$[0m[36mtreemy-ta[32m$[0m[36mtreemy-tas[32m$[0m[36mtreemy-task[32m$[0m[36mtreemy-task-[32m$[0m[36mtreemy-task-a[32m$[0m[36mtreemy-task-ap[32m$[0m[36mtreemy-task-app[32m$[0m[36mtreemy-task-app[[32m$[0m[36mtreemy-task-app[0[32m$[0m[90m#2[32m$[0m[90m#2.B[32m$[0m[90m#2.Bo[32m$[0m[90m#2.Boo[32m$[0m[90m#2.Booti[32m$[0m[90m#2.Bootith[32m$[0m[90m#2.Bootithe[32m$[0m[90m#2.Bootithea[32m$[0m[90m#2.Bootitheal[32m$[0m[90m#2.Bootithealt[32m$[0m[90m#2.Bootithealth[32m$[0m[90m#2.Bootithealthc[32m$[0m[90m#2.Bootithealthch[32m$[0m[90m#2.Bootithealthche[32m$[0m[90m#2.Bootithealthchec[32m$[0m[90m#2.Bootithealthcheck[32m$[0m[90m#2.Bootithealthcheck-[32m$[0m[90m#2.Bootithealthcheck-g[32m$[0m[90m#2.Bootithealthcheck-ga[32m$[0m[90m#2.Bootithealthcheck-gat[32m$[0m[90m#2.Bootithealthcheck-gate[32m$[0m[90m#2.Bootithealthcheck-gated[32m$[0m[90m#2.Bootithealthcheck-gated,z[32m$[0m[90m#2.Bootithealthcheck-gated,ze[32m$[0m[90m#2.Bootithealthcheck-gated,zer[32m$[0m[90m#2.Bootithealthcheck-gated,zeroe[32m$[0m[90m#2.Bootithealthcheck-gated,zeroed[32m$[0m[90m#2.Bootithealthcheck-gated,zeroedi[32m$[0m[90m#2.Bootithealthcheck-gated,zeroedit[32m$[0m[90m#2.Bootithealthcheck-gated,zeroedits[32m$[0m[90m#2.Bootithealthcheck-gated,zeroedits,z[32m$[0m[90m#2.Bootithealthcheck-gated,zeroedits,ze[32m$[0m[90m#2.Bootithealthcheck-gated,zeroedits,zer[32m$[0m[90m#2.Bootithealthcheck-gated,zeroedits,zeroA[32m$[0m[90m#2.Bootithealthcheck-gated,zeroedits,zeroAP[32m$[0m[90m#2.Bootithealthcheck-gated,zeroedits,zeroAPIk[32m$[0m[90m#2.Bootithealthcheck-gated,zeroedits,zeroAPIke[32m$[0m[90m#2.Bootithealthcheck-gated,zeroedits,zeroAPIkey[32m$[0m[90m#2.Bootithealthcheck-gated,zeroedits,zeroAPIkeys[32m$[0m[90m#2.Bootithealthcheck-gated,zeroedits,zeroAPIkeys[[32m$[0m[90m#2.Bootithealthcheck-gated,zeroedits,zeroAPIkeys[0[32m$[0m[36mcdm[32m$[0m[36mcdmy[32m$[0m[36mcdmy-[32m$[0m[36mcdmy-t[32m$[0m[36mcdmy-ta[32m$[0m[36mcdmy-tas[32m$[0m[36mcdmy-task[32m$[0m[36mcdmy-task-[32m$[0m[36mcdmy-task-a[32m$[0m[36mcdmy-task-ap[32m$[0m[36mcdmy-task-app&[32m$[0m[36mcdmy-task-app&&d[32m$[0m[36mcdmy-task-app&&do[32m$[0m[36mcdmy-task-app&&doc[32m$[0m[36mcdmy-task-app&&dock[32m$[0m[36mcdmy-task-app&&docke[32m$[0m[36mcdmy-task-app&&dockerc[32m$[0m[36mcdmy-task-app&&dockerco[32m$[0m[36mcdmy-task-app&&dockercom[32m$[0m[36mcdmy-task-app&&dockercomp[32m$[0m[36mcdmy-task-app&&dockercompo[32m$[0m[36mcdmy-task-app&&dockercompos[32m$[0m[36mcdmy-task-app&&dockercomposeu[32m$[0m[36mcdmy-task-app&&dockercomposeup-[32m$[0m[36mcdmy-task-app&&dockercomposeup-d-[32m$[0m[36mcdmy-task-app&&dockercomposeup-d--[32m$[0m[36mcdmy-task-app&&dockercomposeup-d--b[32m$[0m[36mcdmy-task-app&&dockercomposeup-d--bu[32m$[0m[36mcdmy-task-app&&dockercomposeup-d--bui[32m$[0m[36mcdmy-task-app&&dockercomposeup-d--buil[32m$[0m[36mcdmy-task-app&&dockercomposeup-d--build[32m$[0m[36mcdmy-task-app&&dockercomposeup-d--build[[32m$[0m[36mcdmy-task-app&&dockercomposeup-d--build[0[32m$[0m[90m#3[32m$[0m[90m#3.I[32m$[0m[90m#3.It[32m$[0m[90m#3.It'[32m$[0m[90m#3.It'sl[32m$[0m[90m#3.It'sli[32m$[0m[90m#3.It'sliv[32m$[0m[90m#3.It'slive[32m$[0m[90m#3.It'slive[[32m$[0m[90m#3.It'slive[0[32m$[0m[36mcurllocalhost:5000/api/h[32m$[0m[36mcurllocalhost:5000/api/he[32m$[0m[36mcurllocalhost:5000/api/hea[32m$[0m[36mcurllocalhost:5000/api/heal[32m$[0m[36mcurllocalhost:5000/api/healt[32m$[0m[36mcurllocalhost:5000/api/health[32m$[0m[36mcurllocalhost:5000/api/health[[32m$[0m[36mcurllocalhost:5000/api/health[0[32m$[0m[90m#R[32m$[0m[90m#Re[32m$[0m[90m#Reg[32m$[0m[90m#Regi[32m$[0m[90m#Regis[32m$[0m[90m#Regist[32m$[0m[90m#Registe[32m$[0m[90m#Registeri[32m$[0m[90m#Registeris[32m$[0m[90m#Registeriss[32m$[0m[90m#Registerissu[32m$[0m[90m#Registerissue[32m$[0m[90m#RegisterissuesaJ[32m$[0m[90m#RegisterissuesaJW[32m$[0m[90m#RegisterissuesaJWTi[32m$[0m[90m#RegisterissuesaJWTina[32m$[0m[90m#RegisterissuesaJWTinanh[32m$[0m[90m#RegisterissuesaJWTinanht[32m$[0m[90m#RegisterissuesaJWTinanhtt[32m$[0m[90m#RegisterissuesaJWTinanhttp[32m$[0m[90m#RegisterissuesaJWTinanhttpO[32m$[0m[90m#RegisterissuesaJWTinanhttpOn[32m$[0m[90m#RegisterissuesaJWTinanhttpOnl[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlyc[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlyco[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycoo[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycook[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycooki[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie([32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(n[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(ne[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(nev[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(neve[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(neverl[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(neverlo[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(neverloc[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(neverloca[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(neverlocal[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(neverlocalS[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(neverlocalSt[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(neverlocalSto[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(neverlocalStor[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(neverlocalStora[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(neverlocalStorag[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(neverlocalStorage[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(neverlocalStorage)[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(neverlocalStorage)[[32m$[0m[90m#RegisterissuesaJWTinanhttpOnlycookie(neverlocalStorage)[0[32m$[0m[36mcurl-cc[32m$[0m[36mcurl-cco[32m$[0m[36mcurl-ccoo[32m$[0m[36mcurl-ccook[32m$[0m[36mcurl-ccooki[32m$[0m[36mcurl-ccookie[32m$[0m[36mcurl-ccookies[32m$[0m[36mcurl-ccookies.[32m$[0m[36mcurl-ccookies.t[32m$[0m[36mcurl-ccookies.tx[32m$[0m[36mcurl-ccookies.txt-[32m$[0m[36mcurl-ccookies.txt-XP[32m$[0m[36mcurl-ccookies.txt-XPO[32m$[0m[36mcurl-ccookies.txt-XPOS[32m$[0m[36mcurl-ccookies.txt-XPOSTl[32m$[0m[36mcurl-ccookies.txt-XPOSTlo[32m$[0m[36mcurl-ccookies.txt-XPOSTloc[32m$[0m[36mcurl-ccookies.txt-XPOSTloca[32m$[0m[36mcurl-ccookies.txt-XPOSTlocal[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalh[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalho[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhos[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:50[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:500[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/a[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/ap[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api/[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api/a[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api/au[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api/aut[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api/auth[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api/auth/[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api/auth/r[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api/auth/re[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api/auth/reg[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api/auth/regi[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api/auth/regis[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api/auth/regist[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api/auth/registe[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api/auth/register\[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api/auth/register\[[32m$[0m[36mcurl-ccookies.txt-XPOSTlocalhost:5000/api/auth/register\[0[[3[36[36m-[36m-d'[36m-d'{[36m-d'{"[36m-d'{"e[36m-d'{"em[36m-d'{"ema[36m-d'{"emai[36m-d'{"email[36m-d'{"email"[36m-d'{"email":[36m-d'{"email":"[36m-d'{"email":"y[36m-d'{"email":"yo[36m-d'{"email":"you[36m-d'{"email":"you@[36m-d'{"email":"you@e[36m-d'{"email":"you@ex[36m-d'{"email":"you@exa[36m-d'{"email":"you@exam[36m-d'{"email":"you@examp[36m-d'{"email":"you@exampl[36m-d'{"email":"you@example[36m-d'{"email":"you@example.[36m-d'{"email":"you@example.c[36m-d'{"email":"you@example.co[36m-d'{"email":"you@example.com[36m-d'{"email":"you@example.com"[36m-d'{"email":"you@example.com",[36m-d'{"email":"you@example.com","[36m-d'{"email":"you@example.com","p[36m-d'{"email":"you@example.com","pa[36m-d'{"email":"you@example.com","pas[36m-d'{"email":"you@example.com","pass[36m-d'{"email":"you@example.com","passw[36m-d'{"email":"you@example.com","passwo[36m-d'{"email":"you@example.com","passwor[36m-d'{"email":"you@example.com","password[36m-d'{"email":"you@example.com","password"[36m-d'{"email":"you@example.com","password":[36m-d'{"email":"you@example.com","password":"[36m-d'{"email":"you@example.com","password":"h[36m-d'{"email":"you@example.com","password":"hu[36m-d'{"email":"you@example.com","password":"hun[36m-d'{"email":"you@example.com","password":"hunt[36m-d'{"email":"you@example.com","password":"hunte[36m-d'{"email":"you@example.com","password":"hunter[36m-d'{"email":"you@example.com","password":"hunter2[36m-d'{"email":"you@example.com","password":"hunter22[36m-d'{"email":"you@example.com","password":"hunter22h[36m-d'{"email":"you@example.com","password":"hunter22hu[36m-d'{"email":"you@example.com","password":"hunter22hun[36m-d'{"email":"you@example.com","password":"hunter22hunt[36m-d'{"email":"you@example.com","password":"hunter22hunte[36m-d'{"email":"you@example.com","password":"hunter22hunter[36m-d'{"email":"you@example.com","password":"hunter22hunter"[36m-d'{"email":"you@example.com","password":"hunter22hunter"}[36m-d'{"email":"you@example.com","password":"hunter22hunter"}'[36m-d'{"email":"you@example.com","password":"hunter22hunter"}'[[36m-d'{"email":"you@example.com","password":"hunter22hunter"}'[0[32m$[0m[90m#C[32m$[0m[90m#Cr[32m$[0m[90m#Cre[32m$[0m[90m#Crea[32m$[0m[90m#Creat[32m$[0m[90m#Createap[32m$[0m[90m#Createapr[32m$[0m[90m#Createapro[32m$[0m[90m#Createaproj[32m$[0m[90m#Createaproje[32m$[0m[90m#Createaprojec[32m$[0m[90m#Createaprojecta[32m$[0m[90m#Createaprojectau[32m$[0m[90m#Createaprojectaut[32m$[0m[90m#Createaprojectauthr[32m$[0m[90m#Createaprojectauthre[32m$[0m[90m#Createaprojectauthreq[32m$[0m[90m#Createaprojectauthrequ[32m$[0m[90m#Createaprojectauthrequi[32m$[0m[90m#Createaprojectauthrequir[32m$[0m[90m#Createaprojectauthrequire[32m$[0m[90m#Createaprojectauthrequired[32m$[0m[90m#Createaprojectauthrequired,r[32m$[0m[90m#Createaprojectauthrequired,ro[32m$[0m[90m#Createaprojectauthrequired,rows[32m$[0m[90m#Createaprojectauthrequired,rowsc[32m$[0m[90m#Createaprojectauthrequired,rowsco[32m$[0m[90m#Createaprojectauthrequired,rowscop[32m$[0m[90m#Createaprojectauthrequired,rowscope[32m$[0m[90m#Createaprojectauthrequired,rowscopedt[32m$[0m[90m#Createaprojectauthrequired,rowscopedtot[32m$[0m[90m#Createaprojectauthrequired,rowscopedtoth[32m$[0m[90m#Createaprojectauthrequired,rowscopedtothi[32m$[0m[90m#Createaprojectauthrequired,rowscopedtothisu[32m$[0m[90m#Createaprojectauthrequired,rowscopedtothisus[32m$[0m[90m#Createaprojectauthrequired,rowscopedtothisuse[32m$[0m[90m#Createaprojectauthrequired,rowscopedtothisuser[32m$[0m[90m#Createaprojectauthrequired,rowscopedtothisuser[[32m$[0m[90m#Createaprojectauthrequired,rowscopedtothisuser[0[32m$[0m[36mcurl-bcookies.txt-[32m$[0m[36mcurl-bcookies.txt-XP[32m$[0m[36mcurl-bcookies.txt-XPO[32m$[0m[36mcurl-bcookies.txt-XPOS[32m$[0m[36mcurl-bcookies.txt-XPOSTl[32m$[0m[36mcurl-bcookies.txt-XPOSTlo[32m$[0m[36mcurl-bcookies.txt-XPOSTloc[32m$[0m[36mcurl-bcookies.txt-XPOSTloca[32m$[0m[36mcurl-bcookies.txt-XPOSTlocal[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalh[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalho[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhos[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:50[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:500[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/a[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/ap[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/p[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/pr[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/pro[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/proj[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/proje[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projec[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/project[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"n[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"na[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"nam[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name"[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name":[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name":"[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name":"M[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name":"Myf[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name":"Myfi[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name":"Myfir[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name":"Myfirs[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name":"Myfirstp[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name":"Myfirstpr[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name":"Myfirstpro[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name":"Myfirstproj[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name":"Myfirstproje[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name":"Myfirstprojec[32m$[0m[36mcurl-bcookies.txt-XPOSTlocalhost:5000/api/projects/-d'{"name":"Myfirstproject}}'}'[}'[0[32m$[0m[90m#L[32m$[0m[90m#Li[32m$[0m[90m#Lis[32m$[0m[90m#Listr[32m$[0m[90m#Listre[32m$[0m[90m#Listret[32m$[0m[90m#Listretu[32m$[0m[90m#Listretur[32m$[0m[90m#Listreturn[32m$[0m[90m#Listreturnso[32m$[0m[90m#Listreturnson[32m$[0m[90m#Listreturnsonl[32m$[0m[90m#Listreturnsonlyy[32m$[0m[90m#Listreturnsonlyyo[32m$[0m[90m#Listreturnsonlyyou[32m$[0m[90m#Listreturnsonlyyourr[32m$[0m[90m#Listreturnsonlyyourro[32m$[0m[90m#Listreturnsonlyyourrow[32m$[0m[90m#Listreturnsonlyyourrows[32m$[0m[90m#Listreturnsonlyyourrows[[32m$[0m[90m#Listreturnsonlyyourrows[0[32m$[0m[36mcurl-bcookies.txtl[32m$[0m[36mcurl-bcookies.txtlo[32m$[0m[36mcurl-bcookies.txtloc[32m$[0m[36mcurl-bcookies.txtloca[32m$[0m[36mcurl-bcookies.txtlocal[32m$[0m[36mcurl-bcookies.txtlocalh[32m$[0m[36mcurl-bcookies.txtlocalho[32m$[0m[36mcurl-bcookies.txtlocalhos[32m$[0m[36mcurl-bcookies.txtlocalhost[32m$[0m[36mcurl-bcookies.txtlocalhost:[32m$[0m[36mcurl-bcookies.txtlocalhost:5[32m$[0m[36mcurl-bcookies.txtlocalhost:50[32m$[0m[36mcurl-bcookies.txtlocalhost:500[32m$[0m[36mcurl-bcookies.txtlocalhost:5000[32m$[0m[36mcurl-bcookies.txtlocalhost:5000/[32m$[0m[36mcurl-bcookies.txtlocalhost:5000/a[32m$[0m[36mcurl-bcookies.txtlocalhost:5000/ap[32m$[0m[36mcurl-bcookies.txtlocalhost:5000/api[32m$[0m[36mcurl-bcookies.txtlocalhost:5000/api/[32m$[0m[36mcurl-bcookies.txtlocalhost:5000/api/p[32m$[0m[36mcurl-bcookies.txtlocalhost:5000/api/pr[32m$[0m[36mcurl-bcookies.txtlocalhost:5000/api/pro[32m$[0m[36mcurl-bcookies.txtlocalhost:5000/api/proj[32m$[0m[36mcurl-bcookies.txtlocalhost:5000/api/proje[32m$[0m[36mcurl-bcookies.txtlocalhost:5000/api/projec[32m$[0m[36mcurl-bcookies.txtlocalhost:5000/api/project[32m$[0m[36mcurl-bcookies.txtlocalhost:5000/api/projects[32m$[0m[36mcurl-bcookies.txtlocalhost:5000/api/projects/[32m$[0m[36mcurl-bcookies.txtlocalhost:5000/api/projects/[[32m$[0m[36mcurl-bcookies.txtlocalhost:5000/api/projects/[0[32m$[0m[90m#W[32m$[0m[90m#Wi[32m$[0m[90m#Wit[32m$[0m[90m#With[32m$[0m[90m#Witho[32m$[0m[90m#Withou[32m$[0m[90m#Withoutt[32m$[0m[90m#Withoutth[32m$[0m[90m#Withoutthec[32m$[0m[90m#Withouttheco[32m$[0m[90m#Withoutthecoo[32m$[0m[90m#Withoutthecook[32m$[0m[90m#Withoutthecooki[32m$[0m[90m#Withoutthecookie[32m$[0m[90m#Withoutthecookie,t[32m$[0m[90m#Withoutthecookie,th[32m$[0m[90m#Withoutthecookie,theA[32m$[0m[90m#Withoutthecookie,theAP[32m$[0m[90m#Withoutthecookie,theAPIr[32m$[0m[90m#Withoutthecookie,theAPIre[32m$[0m[90m#Withoutthecookie,theAPIref[32m$[0m[90m#Withoutthecookie,theAPIrefu[32m$[0m[90m#Withoutthecookie,theAPIrefus[32m$[0m[90m#Withoutthecookie,theAPIrefuse[32m$[0m[90m#Withoutthecookie,theAPIrefuses[32m$[0m[90m#Withoutthecookie,theAPIrefuses[[32m$[0m[90m#Withoutthecookie,theAPIrefuses[0[32m$[0m[36mcurllocalhost:5000/api/p[32m$[0m[36mcurllocalhost:5000/api/pr[32m$[0m[36mcurllocalhost:5000/api/pro[32m$[0m[36mcurllocalhost:5000/api/proj[32m$[0m[36mcurllocalhost:5000/api/proje[32m$[0m[36mcurllocalhost:5000/api/projec[32m$[0m[36mcurllocalhost:5000/api/project[32m$[0m[36mcurllocalhost:5000/api/projects[32m$[0m[36mcurllocalhost:5000/api/projects/[32m$[0m[36mcurllocalhost:5000/api/projects/[[32m$[0m[36mcurllocalhost:5000/api/projects/[0[33m{"msg":"Missingcookie\"access_token_cookie\""}[0m \ No newline at end of file