genesis-stack 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/package.json +1 -1
- package/stacks/pieces/django-mysql.md +79 -0
- package/stacks/pieces/django-postgresql.md +78 -0
- package/stacks/pieces/django-sqlite.md +55 -0
- package/stacks/pieces/django.md +166 -0
- package/stacks/pieces/express.md +143 -0
- package/stacks/pieces/java.md +1 -2
- package/stacks/pieces/nextjs.md +153 -0
- package/stacks/pieces/nodejs.md +2 -1
- package/stacks/pieces/python.md +3 -5
- package/stacks/pieces/rails-mysql.md +76 -0
- package/stacks/pieces/rails-postgresql.md +74 -0
- package/stacks/pieces/rails-sqlite.md +60 -0
- package/stacks/pieces/rails.md +161 -0
- package/stacks/pieces/ruby.md +1 -4
- package/stacks/pieces/spring-boot-mysql.md +74 -0
- package/stacks/pieces/spring-boot-postgresql.md +68 -0
- package/stacks/pieces/spring-boot.md +148 -0
package/README.md
CHANGED
|
@@ -54,6 +54,17 @@ consistent backups. `laravel-sqlite` adds Laravel's `DB_DATABASE` filename
|
|
|
54
54
|
binding and `DB_CONNECTION=sqlite` default. Hosts own provisioning; applications
|
|
55
55
|
own schema changes and preservation of existing data during adoption.
|
|
56
56
|
|
|
57
|
+
The `django`, `rails`, `spring-boot`, `express` and `nextjs` pieces require
|
|
58
|
+
their language piece, link the framework's official documentation, and propose
|
|
59
|
+
its conventional Workspace setup, Outputs, Verification and Deployment for
|
|
60
|
+
review during adoption. Their database integrations (`django-*` and `rails-*`
|
|
61
|
+
for PostgreSQL, MySQL and SQLite; `spring-boot-*` for PostgreSQL and MySQL)
|
|
62
|
+
bind the framework's own configuration names without a password default.
|
|
63
|
+
Express and Next.js have no framework ORM, so their applications declare
|
|
64
|
+
database Resources in the project Stack. `express` and `nextjs` conflict because
|
|
65
|
+
both propose how to run the same Node.js process. No starter templates exist for
|
|
66
|
+
these frameworks yet.
|
|
67
|
+
|
|
57
68
|
## Resource-estimate proposals
|
|
58
69
|
|
|
59
70
|
JSKIT proposes a host's optional `Resource estimates` section for its concrete
|
package/package.json
CHANGED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Stack piece: django-mysql
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
Django MySQL database engine, driver, connection settings, migration, and test
|
|
6
|
+
database conventions. Database documentation:
|
|
7
|
+
https://docs.djangoproject.com/en/stable/ref/databases/
|
|
8
|
+
|
|
9
|
+
## Requires
|
|
10
|
+
|
|
11
|
+
- `django`
|
|
12
|
+
- `mysql`
|
|
13
|
+
|
|
14
|
+
## Conflicts
|
|
15
|
+
|
|
16
|
+
- `django-postgresql`
|
|
17
|
+
- `django-sqlite`
|
|
18
|
+
|
|
19
|
+
## Environment defaults
|
|
20
|
+
|
|
21
|
+
- Default `DB_HOST`: `127.0.0.1`
|
|
22
|
+
- Default `DB_PORT`: `3306`
|
|
23
|
+
- Default `DB_NAME`: `django`
|
|
24
|
+
- Default `DB_USER`: `root`
|
|
25
|
+
|
|
26
|
+
## Resources
|
|
27
|
+
|
|
28
|
+
```json genesis-resource
|
|
29
|
+
{
|
|
30
|
+
"id": "database",
|
|
31
|
+
"kind": "mysql",
|
|
32
|
+
"environmentAlternatives": [
|
|
33
|
+
{
|
|
34
|
+
"bindings": {
|
|
35
|
+
"database": "DB_NAME",
|
|
36
|
+
"host": "DB_HOST",
|
|
37
|
+
"password": "DB_PASSWORD",
|
|
38
|
+
"port": "DB_PORT",
|
|
39
|
+
"username": "DB_USER"
|
|
40
|
+
},
|
|
41
|
+
"allowEmpty": ["password"],
|
|
42
|
+
"preferred": true
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"bindings": {
|
|
46
|
+
"url": "DATABASE_URL"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
"optionalBindings": {
|
|
51
|
+
"testDatabase": "TEST_DB_NAME"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Guidance
|
|
57
|
+
|
|
58
|
+
- Use `ENGINE: "django.db.backends.mysql"` with the `mysqlclient` driver.
|
|
59
|
+
It compiles against the MySQL or MariaDB client library and needs its
|
|
60
|
+
headers, `pkg-config` and a C compiler when no binary wheel matches; the
|
|
61
|
+
database server itself is not enough.
|
|
62
|
+
- Build `DATABASES["default"]` from `DB_NAME`, `DB_USER`, `DB_PASSWORD`,
|
|
63
|
+
`DB_HOST` and `DB_PORT`, or parse `DATABASE_URL` with the app's existing
|
|
64
|
+
parser (for example `dj-database-url`) when it is set. Keep one source of
|
|
65
|
+
truth; do not merge partial values from both.
|
|
66
|
+
- Set `OPTIONS: {"charset": "utf8mb4", "init_command": "SET sql_mode='STRICT_TRANS_TABLES'"}`
|
|
67
|
+
so text is stored losslessly and invalid values fail instead of being
|
|
68
|
+
truncated.
|
|
69
|
+
- When `TEST_DB_NAME` is supplied, set `DATABASES["default"]["TEST"]["NAME"]`
|
|
70
|
+
to it and run tests with `--keepdb`; Django reuses the existing database.
|
|
71
|
+
Without it, the user needs permission to create `test_<NAME>`.
|
|
72
|
+
|
|
73
|
+
## Adoption
|
|
74
|
+
|
|
75
|
+
- Confirm the driver, the settings source of each connection value, any
|
|
76
|
+
`DATABASE_URL` parser, `OPTIONS` and the test database name from the
|
|
77
|
+
settings module before declaring readiness or connecting. Keep the project
|
|
78
|
+
Resource contract aligned with names the application deliberately uses
|
|
79
|
+
instead.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Stack piece: django-postgresql
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
Django PostgreSQL database engine, driver, connection settings, migration, and test
|
|
6
|
+
database conventions. Database documentation:
|
|
7
|
+
https://docs.djangoproject.com/en/stable/ref/databases/
|
|
8
|
+
|
|
9
|
+
## Requires
|
|
10
|
+
|
|
11
|
+
- `django`
|
|
12
|
+
- `postgresql`
|
|
13
|
+
|
|
14
|
+
## Conflicts
|
|
15
|
+
|
|
16
|
+
- `django-mysql`
|
|
17
|
+
- `django-sqlite`
|
|
18
|
+
|
|
19
|
+
## Environment defaults
|
|
20
|
+
|
|
21
|
+
- Default `DB_HOST`: `127.0.0.1`
|
|
22
|
+
- Default `DB_PORT`: `5432`
|
|
23
|
+
- Default `DB_NAME`: `django`
|
|
24
|
+
- Default `DB_USER`: `postgres`
|
|
25
|
+
|
|
26
|
+
## Resources
|
|
27
|
+
|
|
28
|
+
```json genesis-resource
|
|
29
|
+
{
|
|
30
|
+
"id": "database",
|
|
31
|
+
"kind": "postgresql",
|
|
32
|
+
"environmentAlternatives": [
|
|
33
|
+
{
|
|
34
|
+
"bindings": {
|
|
35
|
+
"database": "DB_NAME",
|
|
36
|
+
"host": "DB_HOST",
|
|
37
|
+
"password": "DB_PASSWORD",
|
|
38
|
+
"port": "DB_PORT",
|
|
39
|
+
"username": "DB_USER"
|
|
40
|
+
},
|
|
41
|
+
"allowEmpty": ["password"],
|
|
42
|
+
"preferred": true
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"bindings": {
|
|
46
|
+
"url": "DATABASE_URL"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
"optionalBindings": {
|
|
51
|
+
"testDatabase": "TEST_DB_NAME"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Guidance
|
|
57
|
+
|
|
58
|
+
- Use `ENGINE: "django.db.backends.postgresql"` with the `psycopg` (version 3)
|
|
59
|
+
driver; `psycopg[binary]` needs no build toolchain. Older apps on
|
|
60
|
+
`psycopg2` keep it until a deliberate upgrade.
|
|
61
|
+
- Build `DATABASES["default"]` from `DB_NAME`, `DB_USER`, `DB_PASSWORD`,
|
|
62
|
+
`DB_HOST` and `DB_PORT`, or parse `DATABASE_URL` with the app's existing
|
|
63
|
+
parser (for example `dj-database-url`) when it is set. Keep one source of
|
|
64
|
+
truth; do not merge partial values from both.
|
|
65
|
+
- When `TEST_DB_NAME` is supplied, set `DATABASES["default"]["TEST"]["NAME"]`
|
|
66
|
+
to it and run tests with `--keepdb`: Django then reuses the existing
|
|
67
|
+
database instead of needing permission to create one. Without it, the test
|
|
68
|
+
role needs `CREATEDB`.
|
|
69
|
+
- Keep schema changes in Django migrations; avoid raw SQL schema edits
|
|
70
|
+
outside `RunSQL` operations committed with the app.
|
|
71
|
+
|
|
72
|
+
## Adoption
|
|
73
|
+
|
|
74
|
+
- Confirm the driver, the settings source of each connection value, any
|
|
75
|
+
`DATABASE_URL` parser, `CONN_MAX_AGE`/pooling options and the test database
|
|
76
|
+
name from the settings module before declaring readiness or connecting.
|
|
77
|
+
Keep the project Resource contract aligned with names the application
|
|
78
|
+
deliberately uses instead.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Stack piece: django-sqlite
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
Django SQLite database file, migration, and test database conventions.
|
|
6
|
+
Database documentation:
|
|
7
|
+
https://docs.djangoproject.com/en/stable/ref/databases/#sqlite-notes
|
|
8
|
+
|
|
9
|
+
## Requires
|
|
10
|
+
|
|
11
|
+
- `django`
|
|
12
|
+
- `sqlite`
|
|
13
|
+
|
|
14
|
+
## Conflicts
|
|
15
|
+
|
|
16
|
+
- `django-postgresql`
|
|
17
|
+
- `django-mysql`
|
|
18
|
+
|
|
19
|
+
## Resources
|
|
20
|
+
|
|
21
|
+
```json genesis-resource
|
|
22
|
+
{
|
|
23
|
+
"id": "database",
|
|
24
|
+
"kind": "sqlite",
|
|
25
|
+
"environmentAlternatives": [
|
|
26
|
+
{
|
|
27
|
+
"bindings": {
|
|
28
|
+
"database": "DB_NAME"
|
|
29
|
+
},
|
|
30
|
+
"preferred": true
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Guidance
|
|
37
|
+
|
|
38
|
+
- Use `ENGINE: "django.db.backends.sqlite3"` and read `NAME` from `DB_NAME`.
|
|
39
|
+
Preserve an absolute filename supplied by the environment. Only a
|
|
40
|
+
standalone checkout without `DB_NAME` falls back to a path such as
|
|
41
|
+
`BASE_DIR / "db.sqlite3"`, which stays out of Git.
|
|
42
|
+
- Repeated setup must preserve the file, its records and the migration
|
|
43
|
+
ledger: run `migrate --noinput`, never delete or recreate the file as
|
|
44
|
+
routine preparation.
|
|
45
|
+
- Tests use an in-memory database unless `DATABASES["default"]["TEST"]["NAME"]`
|
|
46
|
+
names a file; never point it at the development file.
|
|
47
|
+
- SQLite allows one writer at a time. Keep Gunicorn to a small worker count
|
|
48
|
+
and short transactions, and consider `"OPTIONS": {"transaction_mode": "IMMEDIATE"}`
|
|
49
|
+
with a `timeout` when concurrent writes report "database is locked".
|
|
50
|
+
|
|
51
|
+
## Adoption
|
|
52
|
+
|
|
53
|
+
- Read the settings module's `DATABASES` before declaring readiness and keep
|
|
54
|
+
any existing database file and its data when adopting supplied storage.
|
|
55
|
+
Verify migrations against the configured file and keep tests separate.
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Stack piece: django
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
Django web application, settings, migrations, management commands, static
|
|
6
|
+
files, test runner, and production serving conventions. Identified by
|
|
7
|
+
`manage.py` beside a settings module, with `django` in `requirements.txt` or
|
|
8
|
+
`pyproject.toml`. Authoritative framework documentation:
|
|
9
|
+
https://docs.djangoproject.com/
|
|
10
|
+
|
|
11
|
+
## Requires
|
|
12
|
+
|
|
13
|
+
- `python`
|
|
14
|
+
|
|
15
|
+
## Guidance
|
|
16
|
+
|
|
17
|
+
- Use the Django version the application pins and follow the matching
|
|
18
|
+
official documentation. Preserve Django's apps, models, forms, class-based
|
|
19
|
+
or function views, middleware, signals, admin and management commands
|
|
20
|
+
instead of adding parallel framework plumbing.
|
|
21
|
+
- The development server binds the supplied loopback host and port:
|
|
22
|
+
`manage.py runserver {host}:{port}`. Never bind `0.0.0.0` to make a proxy
|
|
23
|
+
work.
|
|
24
|
+
- Behind a loopback development reverse proxy that rewrites `Host` and sends
|
|
25
|
+
`X-Forwarded-Host`, `X-Forwarded-Proto` and `X-Forwarded-Port`, set
|
|
26
|
+
`USE_X_FORWARDED_HOST = True`, `USE_X_FORWARDED_PORT = True` and
|
|
27
|
+
`SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")`. This is
|
|
28
|
+
safe only because the server is reachable solely through that proxy; keep
|
|
29
|
+
the bind on loopback. Absolute URLs, redirects and `request.is_secure()`
|
|
30
|
+
then use the browser-facing origin. Without `SECURE_PROXY_SSL_HEADER`, an
|
|
31
|
+
HTTPS browser origin makes every form POST fail Django's CSRF origin check.
|
|
32
|
+
- Read `ALLOWED_HOSTS` from a comma-separated `DJANGO_ALLOWED_HOSTS`. When it
|
|
33
|
+
is unset, allow `["*"]` only while `DEBUG` is on, because the browser-facing
|
|
34
|
+
development host is not known in advance; otherwise default to
|
|
35
|
+
`["127.0.0.1", "localhost"]`. Production lists its public host names and
|
|
36
|
+
keeps `127.0.0.1` so a loopback readiness probe is admitted.
|
|
37
|
+
- Read `CSRF_TRUSTED_ORIGINS` from a comma-separated
|
|
38
|
+
`DJANGO_CSRF_TRUSTED_ORIGINS`. It is usually unnecessary once the
|
|
39
|
+
forwarded host and protocol are trusted, because Django then compares the
|
|
40
|
+
`Origin` header with the browser-facing origin. Never trust loopback or
|
|
41
|
+
wildcard origins to make a failing form POST pass; fix the proxy trust
|
|
42
|
+
instead.
|
|
43
|
+
- Read `DEBUG` from `DJANGO_DEBUG` (`1` enables it) and default it off. Set
|
|
44
|
+
it in the development environment only.
|
|
45
|
+
- `XFrameOptionsMiddleware` answers `X-Frame-Options: DENY`, so a development
|
|
46
|
+
tool that shows the application inside a frame stays blank. When that is
|
|
47
|
+
needed, remove the middleware only while `DEBUG` is on; production keeps it.
|
|
48
|
+
- Read `SECRET_KEY` from `DJANGO_SECRET_KEY` and fail when it is missing.
|
|
49
|
+
Replace the insecure key `startproject` writes into settings. Generate each
|
|
50
|
+
environment's value with
|
|
51
|
+
`python -c 'from django.core.management.utils import get_random_secret_key as k; print(k())'`
|
|
52
|
+
and supply it through that environment's secret facility; never commit it
|
|
53
|
+
or write it into a generated dotenv file. Development and production use
|
|
54
|
+
different keys. Every `manage.py` command imports settings, so supply the
|
|
55
|
+
development key before workspace setup runs `migrate`.
|
|
56
|
+
- Setup and deployment run `manage.py migrate --noinput`. `makemigrations` is
|
|
57
|
+
authoring: run it after model changes and commit the generated files. Never
|
|
58
|
+
use `flush`, `migrate --fake`, `reset_db`, or delete or rewrite applied
|
|
59
|
+
migrations as routine preparation.
|
|
60
|
+
- Seed reference data and development users through idempotent management
|
|
61
|
+
commands (`get_or_create`/`update_or_create`, `set_password`) or data
|
|
62
|
+
migrations. `createsuperuser --noinput` fails once the user exists, so it
|
|
63
|
+
is a one-off command, never a repeated setup step: seed the development
|
|
64
|
+
administrator and a non-administrator in one app-owned command that reads
|
|
65
|
+
their passwords from the environment (for example
|
|
66
|
+
`DJANGO_SUPERUSER_PASSWORD`) and run it after `migrate` in the project's
|
|
67
|
+
setup. Never hard-code production credentials.
|
|
68
|
+
- Static files: set `STATIC_ROOT`, run `collectstatic --noinput` in
|
|
69
|
+
deployment, and add `whitenoise.middleware.WhiteNoiseMiddleware` directly
|
|
70
|
+
after `SecurityMiddleware`; `runserver` serves static files only while
|
|
71
|
+
`DEBUG` is on. Keep `STATIC_ROOT` and media uploads out of Git.
|
|
72
|
+
- Tests: `manage.py test` creates `test_<NAME>` and needs permission to
|
|
73
|
+
create databases. When the environment supplies a separate disposable test
|
|
74
|
+
database instead, set `DATABASES["default"]["TEST"]["NAME"]` from it and keep
|
|
75
|
+
`--keepdb`, which reuses an existing database rather than creating or
|
|
76
|
+
dropping one. Never point tests at the development or production database.
|
|
77
|
+
Suites that create users spend most of their time hashing passwords: set
|
|
78
|
+
`PASSWORD_HASHERS = ["django.contrib.auth.hashers.MD5PasswordHasher"]` only
|
|
79
|
+
in a test settings module or under `if sys.argv[1:2] == ["test"]:`; never
|
|
80
|
+
outside tests.
|
|
81
|
+
- Production serves with Gunicorn through an app-owned `gunicorn.conf.py`
|
|
82
|
+
(read from the working directory by default) containing
|
|
83
|
+
`wsgi_app = "<project>.wsgi"` and
|
|
84
|
+
`bind = f"{os.environ.get('HOST', '127.0.0.1')}:{os.environ.get('PORT', '8000')}"`.
|
|
85
|
+
Add `gunicorn` and `whitenoise` to the requirements. Keep `DEBUG` off,
|
|
86
|
+
enable `SESSION_COOKIE_SECURE` and `CSRF_COOKIE_SECURE` behind HTTPS, and
|
|
87
|
+
review `manage.py check --deploy`. It rejects the console email backend that
|
|
88
|
+
recent `startproject` templates configure (`MAILERS` or `EMAIL_BACKEND`), so
|
|
89
|
+
select the production email backend and its credentials from the
|
|
90
|
+
environment. When `SECURE_SSL_REDIRECT` is on, add the
|
|
91
|
+
readiness path to `SECURE_REDIRECT_EXEMPT` so a plain loopback probe is not
|
|
92
|
+
redirected.
|
|
93
|
+
- The proposed readiness path is the admin login page `/admin/login/`. An
|
|
94
|
+
application without `django.contrib.admin` adds a small unauthenticated
|
|
95
|
+
health view and updates its Outputs and Deployment readiness to it.
|
|
96
|
+
- The proposals install from `requirements.txt` into `.venv`. Poetry, uv or
|
|
97
|
+
other `pyproject.toml` workflows replace the install lines in the project's
|
|
98
|
+
sections with that tool's equivalent.
|
|
99
|
+
- Select `django-postgresql`, `django-mysql` or `django-sqlite` for the
|
|
100
|
+
database settings; it owns the engine and environment names.
|
|
101
|
+
|
|
102
|
+
## Adoption
|
|
103
|
+
|
|
104
|
+
- Inspect `manage.py`, the settings module (single file or split
|
|
105
|
+
base/development/production modules), `DJANGO_SETTINGS_MODULE`,
|
|
106
|
+
`requirements*.txt` or `pyproject.toml` and its lock file, `wsgi.py`/`asgi.py`,
|
|
107
|
+
`INSTALLED_APPS`, `MIDDLEWARE`, `DATABASES`, and existing environment names
|
|
108
|
+
before changing project contracts. Preserve the pinned Django major.
|
|
109
|
+
- Record the real install, migrate, seed, test, static and serving commands.
|
|
110
|
+
Replace any proposed line that does not match (ASGI servers such as
|
|
111
|
+
Uvicorn or Daphne, a different settings module, a non-admin readiness path)
|
|
112
|
+
before claiming readiness.
|
|
113
|
+
- Confirm how settings read the secret key, debug flag, allowed hosts, CSRF
|
|
114
|
+
origins and proxy headers; move committed values into the environment
|
|
115
|
+
without changing their meaning.
|
|
116
|
+
- Select the matching Django database piece when the app uses PostgreSQL,
|
|
117
|
+
MySQL or SQLite.
|
|
118
|
+
|
|
119
|
+
## Workspace setup
|
|
120
|
+
|
|
121
|
+
- Prepare `Create virtual environment` with `python` when `manage.py` exists: `python3` `-m` `venv` `.venv`
|
|
122
|
+
- Prepare `Install Python dependencies` with `python` if `requirements.txt` exists: `.venv/bin/python` `-m` `pip` `install` `-r` `requirements.txt`
|
|
123
|
+
- Prepare `Apply migrations` with `python` when `manage.py` exists: `.venv/bin/python` `manage.py` `migrate` `--noinput`
|
|
124
|
+
|
|
125
|
+
## Outputs
|
|
126
|
+
|
|
127
|
+
### Target `app`: Run Django app
|
|
128
|
+
|
|
129
|
+
- Default.
|
|
130
|
+
- Mode: `interactive`
|
|
131
|
+
- Runtimes: `python`
|
|
132
|
+
- Run `Develop`: `.venv/bin/python` `manage.py` `runserver` `{host}:{port}`
|
|
133
|
+
|
|
134
|
+
#### Presentation
|
|
135
|
+
|
|
136
|
+
- Kind: `web`
|
|
137
|
+
- Preferred port: `8000`
|
|
138
|
+
- URL path: `/`
|
|
139
|
+
- Ready when: `GET` `/admin/login/` returns `200`
|
|
140
|
+
|
|
141
|
+
## Verification
|
|
142
|
+
|
|
143
|
+
- Verify `application`: `.venv/bin/python` `manage.py` `test` `--noinput` `--keepdb`
|
|
144
|
+
|
|
145
|
+
## Deployment
|
|
146
|
+
|
|
147
|
+
- Runtimes: `python`
|
|
148
|
+
- Recreate on restore: `.venv`
|
|
149
|
+
- Ready when: `GET` `/admin/login/` returns `200`
|
|
150
|
+
- Prepare `Create virtual environment`: `python3` `-m` `venv` `.venv`
|
|
151
|
+
- Prepare `Install dependencies`: `.venv/bin/python` `-m` `pip` `install` `-r` `requirements.txt`
|
|
152
|
+
- Build `Collect static files`: `.venv/bin/python` `manage.py` `collectstatic` `--noinput`
|
|
153
|
+
- Migrate `Apply migrations`: `.venv/bin/python` `manage.py` `migrate` `--noinput`
|
|
154
|
+
- Serve `Start`: `.venv/bin/gunicorn`
|
|
155
|
+
|
|
156
|
+
## Deslop
|
|
157
|
+
|
|
158
|
+
- Preserve Django's apps, models, managers, querysets, forms, views,
|
|
159
|
+
middleware, signals, admin registrations and management commands as the
|
|
160
|
+
owners of their behavior.
|
|
161
|
+
- Keep validation in forms, serializers or model `clean` methods and
|
|
162
|
+
authorization in views, permissions or decorators. Remove service layers,
|
|
163
|
+
repositories or helper modules only when they merely rename ORM or framework
|
|
164
|
+
operations.
|
|
165
|
+
- Preserve migration history; cleanup is not permission to squash, rewrite or
|
|
166
|
+
delete applied migrations or change model behavior.
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Stack piece: express
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
Express HTTP server, routing, middleware, session, proxy trust, and production
|
|
6
|
+
serving conventions. An Express application declares `express` in
|
|
7
|
+
`package.json` and starts from an entry such as `app.js`, `server.js`,
|
|
8
|
+
`src/index.*` or express-generator's `bin/www`. Authoritative framework
|
|
9
|
+
documentation: https://expressjs.com/
|
|
10
|
+
|
|
11
|
+
## Requires
|
|
12
|
+
|
|
13
|
+
- `nodejs`
|
|
14
|
+
|
|
15
|
+
## Conflicts
|
|
16
|
+
|
|
17
|
+
- `nextjs`
|
|
18
|
+
|
|
19
|
+
## Guidance
|
|
20
|
+
|
|
21
|
+
- Read the authoritative documentation at `https://expressjs.com/` and match
|
|
22
|
+
the installed Express major. Express 5 changes route path syntax, rejected
|
|
23
|
+
promise handling and `req.host`; follow
|
|
24
|
+
`https://expressjs.com/en/guide/migrating-5.html` only for an intended
|
|
25
|
+
upgrade. Preserve the existing module system, router layout, template
|
|
26
|
+
engine and lockfile manager; a pnpm or Yarn lockfile replaces the proposed
|
|
27
|
+
npm lines with that manager's equivalents.
|
|
28
|
+
- Listen on the host and port supplied through the environment:
|
|
29
|
+
`server.listen(Number(process.env.PORT ?? 3000), process.env.HOST ?? '127.0.0.1')`.
|
|
30
|
+
express-generator's `bin/www` reads `PORT` but listens on every interface;
|
|
31
|
+
pass the host. Let a taken port fail instead of choosing another one. The
|
|
32
|
+
proposed development Run is `npm start`; when the project develops through
|
|
33
|
+
a watch script (`node --watch`, nodemon, tsx), point Run at that script.
|
|
34
|
+
- Behind a loopback development reverse proxy that rewrites `Host` to the
|
|
35
|
+
loopback address and sends `X-Forwarded-Host`, `X-Forwarded-Proto` and
|
|
36
|
+
`X-Forwarded-Port`, set `app.set('trust proxy', 'loopback')` before any
|
|
37
|
+
middleware so `req.protocol`, `req.secure`, `req.hostname`, Express 5
|
|
38
|
+
`req.host` and `req.ip` describe the browser-facing request. Never use
|
|
39
|
+
`trust proxy` `true` for a server reachable without that proxy. Express
|
|
40
|
+
ignores `X-Forwarded-Port`, and Express 4 `req.hostname` drops the port.
|
|
41
|
+
Prefer relative redirects (`res.redirect('/login')`) and root-relative asset
|
|
42
|
+
URLs; build an absolute URL from `req.protocol` and Express 5 `req.host`, or
|
|
43
|
+
from a configured public origin, never from the raw `Host` header. On
|
|
44
|
+
Express 4 take the host from `X-Forwarded-Host` only when
|
|
45
|
+
`req.app.get('trust proxy fn')(req.socket.remoteAddress, 0)` accepts the
|
|
46
|
+
peer, and from `Host` otherwise.
|
|
47
|
+
- Express has no host allow-list or CSRF protection of its own. When the app
|
|
48
|
+
adds them, keep a session-bound CSRF token (or a maintained token library)
|
|
49
|
+
for form posts; an `Origin` check must accept the origin built from the
|
|
50
|
+
trusted forwarded host as well as the raw `Host`, because a development
|
|
51
|
+
proxy may present same-origin requests with a loopback `Origin`. A host or
|
|
52
|
+
CORS allow-list must also admit loopback for the health probe.
|
|
53
|
+
- Sessions use `express-session` with `secret: process.env.SESSION_SECRET`,
|
|
54
|
+
generated with `openssl rand -base64 32`, supplied through the environment,
|
|
55
|
+
never committed and never written into a generated dotenv file; refuse to
|
|
56
|
+
start in production without it. Development may fall back to a random
|
|
57
|
+
per-process secret, which ends sessions on restart. Use
|
|
58
|
+
`cookie: { secure: 'auto', httpOnly: true, sameSite: 'lax' }`; `'auto'`
|
|
59
|
+
depends on the proxy trust above. The default MemoryStore leaks and loses
|
|
60
|
+
sessions on restart: production uses a persistent store backed by the app's
|
|
61
|
+
database or cache.
|
|
62
|
+
- Register an unauthenticated `GET /health` returning `200` before session,
|
|
63
|
+
authentication, CSRF and HTTPS-redirect middleware. Keep it cheap and free
|
|
64
|
+
of writes. The proposed Outputs and Deployment readiness use it; an app
|
|
65
|
+
with another health path changes both.
|
|
66
|
+
- Serve static files with `express.static(path.join(__dirname, 'public'))`
|
|
67
|
+
or the ESM equivalent. A bundler or TypeScript build adds a Workspace setup
|
|
68
|
+
step and a Deployment Build step and serves the compiled output.
|
|
69
|
+
- Express has no ORM. Select the database component and record the app's own
|
|
70
|
+
migration tool (Prisma, Drizzle, Knex, Sequelize, TypeORM) as Workspace
|
|
71
|
+
setup and Deployment Migrate steps, for example `prisma migrate deploy` or
|
|
72
|
+
`knex migrate:latest`. Never run `prisma migrate dev`, `prisma db push` or
|
|
73
|
+
`sync({ force: true })` against supplied data. Seeds are idempotent
|
|
74
|
+
upserts. Tests use a separate disposable database, never the development
|
|
75
|
+
one.
|
|
76
|
+
- Deployment installs with `npm ci --omit=dev` (a lockfile is required) and
|
|
77
|
+
serves `npm start`, which receives `HOST` and `PORT` only through the
|
|
78
|
+
environment. Set `NODE_ENV=production` in the production environment, not
|
|
79
|
+
as a project-wide default: it enables view caching and stops the error
|
|
80
|
+
handler exposing stack traces. Exclude `/health` from any HTTPS redirect or
|
|
81
|
+
host check, and close the server on `SIGTERM`. `npm start` runs the server
|
|
82
|
+
under npm and a shell that do not pass `SIGTERM` on, so the supervisor must
|
|
83
|
+
signal the whole process group or serve `node <entry>` directly.
|
|
84
|
+
- When the app has login, hash passwords with bcrypt or argon2 and store a
|
|
85
|
+
role. Seed one development administrator and one ordinary user through an
|
|
86
|
+
idempotent script that reads their passwords from the environment; never
|
|
87
|
+
hard-code production credentials.
|
|
88
|
+
|
|
89
|
+
## Adoption
|
|
90
|
+
|
|
91
|
+
- Inventory `package.json` (Express major, `type`, `main`, `start`/`dev`/`test`
|
|
92
|
+
scripts), the lockfile, the entry file and its `listen` call, middleware
|
|
93
|
+
order, session store, template engine, authentication library, database
|
|
94
|
+
and migration tool, and any TypeScript or bundler build.
|
|
95
|
+
- Replace every proposal line that does not match before claiming readiness.
|
|
96
|
+
Many Express apps (express-generator included) have no `test` script: record
|
|
97
|
+
the real check instead of inventing `npm test`.
|
|
98
|
+
- Make the server honour `HOST`/`PORT`, trust only the loopback proxy, and
|
|
99
|
+
expose `/health`. Select the matching database component.
|
|
100
|
+
- An Express server that hosts Next.js through a custom server is a Next.js
|
|
101
|
+
project; select `nextjs` instead and keep the custom server project-owned.
|
|
102
|
+
|
|
103
|
+
## Workspace setup
|
|
104
|
+
|
|
105
|
+
- Prepare `Install dependencies` with `nodejs` when `package.json` exists: `npm` `install`
|
|
106
|
+
|
|
107
|
+
## Outputs
|
|
108
|
+
|
|
109
|
+
### Target `app`: Run Express app
|
|
110
|
+
|
|
111
|
+
- Default.
|
|
112
|
+
- Mode: `interactive`
|
|
113
|
+
- Runtimes: `nodejs`
|
|
114
|
+
- Run `Develop`: `npm` `start`
|
|
115
|
+
|
|
116
|
+
#### Presentation
|
|
117
|
+
|
|
118
|
+
- Kind: `web`
|
|
119
|
+
- Preferred port: `3000`
|
|
120
|
+
- URL path: `/`
|
|
121
|
+
- Ready when: `GET` `/health` returns `200`
|
|
122
|
+
|
|
123
|
+
## Verification
|
|
124
|
+
|
|
125
|
+
- Verify `application`: `npm` `test`
|
|
126
|
+
|
|
127
|
+
## Deployment
|
|
128
|
+
|
|
129
|
+
- Runtimes: `nodejs`
|
|
130
|
+
- Recreate on restore: `node_modules`
|
|
131
|
+
- Ready when: `GET` `/health` returns `200`
|
|
132
|
+
- Prepare `Install dependencies`: `npm` `ci` `--omit=dev`
|
|
133
|
+
- Serve `Start`: `npm` `start`
|
|
134
|
+
|
|
135
|
+
## Deslop
|
|
136
|
+
|
|
137
|
+
- Keep middleware order meaningful: proxy trust, health, static files, body
|
|
138
|
+
parsing, session, authentication, routers, 404, then one error handler.
|
|
139
|
+
- Use `express.Router` modules over wrapper frameworks that rename Express
|
|
140
|
+
routing. On Express 5 let rejected promises reach the error handler instead
|
|
141
|
+
of repeating try/catch blocks; on Express 4 keep the app's existing pattern.
|
|
142
|
+
- Preserve routes, response shapes, cookies, the module system and the
|
|
143
|
+
lockfile manager.
|
package/stacks/pieces/java.md
CHANGED
|
@@ -46,8 +46,7 @@ Java package, public type, dependency, lifecycle, and test conventions.
|
|
|
46
46
|
connected source.
|
|
47
47
|
- Running a web process: bind the supplied listen host and port, trust forwarded
|
|
48
48
|
headers only from a loopback proxy, and read secrets from the environment.
|
|
49
|
-
Spring Boot
|
|
50
|
-
`server.forward-headers-strategy=framework`.
|
|
49
|
+
For Spring Boot select `spring-boot`; its piece owns the framework traps.
|
|
51
50
|
|
|
52
51
|
## Connected development
|
|
53
52
|
|