codeninja 2.0.0
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/.gitattributes +11 -0
- package/README.md +293 -0
- package/agent/database-agent.md +504 -0
- package/agent/designs/README.md +10 -0
- package/agent/global-agent.md +236 -0
- package/agent/nodejs-agent.md +406 -0
- package/agent/reactjs-agent.md +260 -0
- package/cli.js +352 -0
- package/commands/audit.workflow.md +111 -0
- package/commands/create-api.workflow.md +99 -0
- package/commands/db-add-index.workflow.md +97 -0
- package/commands/db-create-table.workflow.md +132 -0
- package/commands/db-drop-table.workflow.md +103 -0
- package/commands/db-modify-table.workflow.md +159 -0
- package/commands/db-seed.workflow.md +99 -0
- package/commands/db-sync.workflow.md +100 -0
- package/commands/design.workflow.md +66 -0
- package/commands/initialize-project.workflow.md +500 -0
- package/commands/integrate-api.workflow.md +448 -0
- package/commands/modularize.workflow.md +329 -0
- package/commands/refactor.workflow.md +70 -0
- package/commands/sync.workflow.md +962 -0
- package/commands/test.workflow.md +40 -0
- package/commands/validate-page.workflow.md +543 -0
- package/mcp-server.js +842 -0
- package/package.json +24 -0
- package/tasks/README.md +283 -0
- package/tasks/add-health-route.task.md +103 -0
- package/tasks/ask-api-integration-scope.task.md +34 -0
- package/tasks/ask-api-key.task.md +23 -0
- package/tasks/ask-api-version.task.md +28 -0
- package/tasks/ask-client-type.task.md +24 -0
- package/tasks/ask-column-enum-values.task.md +51 -0
- package/tasks/ask-column-is-enum.task.md +39 -0
- package/tasks/ask-column-name.task.md +39 -0
- package/tasks/ask-column-position.task.md +39 -0
- package/tasks/ask-column-type.task.md +59 -0
- package/tasks/ask-database-config.task.md +66 -0
- package/tasks/ask-database-host.task.md +16 -0
- package/tasks/ask-database-name.task.md +18 -0
- package/tasks/ask-database-port.task.md +23 -0
- package/tasks/ask-database-type.task.md +30 -0
- package/tasks/ask-database-user.task.md +14 -0
- package/tasks/ask-design-description.task.md +16 -0
- package/tasks/ask-design-target.task.md +24 -0
- package/tasks/ask-encrypted-transport.task.md +25 -0
- package/tasks/ask-encryption-iv.task.md +23 -0
- package/tasks/ask-encryption-key.task.md +23 -0
- package/tasks/ask-feature-name.task.md +20 -0
- package/tasks/ask-http-method.task.md +21 -0
- package/tasks/ask-index-columns.task.md +46 -0
- package/tasks/ask-index-file-placement.task.md +33 -0
- package/tasks/ask-index-sort-order.task.md +37 -0
- package/tasks/ask-index-type.task.md +42 -0
- package/tasks/ask-init-mode.task.md +28 -0
- package/tasks/ask-linked-service.task.md +57 -0
- package/tasks/ask-modify-operation.task.md +36 -0
- package/tasks/ask-modularize-scope.task.md +31 -0
- package/tasks/ask-module-name.task.md +30 -0
- package/tasks/ask-new-column-name.task.md +21 -0
- package/tasks/ask-new-table-name.task.md +22 -0
- package/tasks/ask-old-column-name.task.md +22 -0
- package/tasks/ask-package-author.task.md +16 -0
- package/tasks/ask-package-name.task.md +23 -0
- package/tasks/ask-page-path.task.md +40 -0
- package/tasks/ask-primary-table.task.md +30 -0
- package/tasks/ask-project-figma.task.md +71 -0
- package/tasks/ask-project-info-doc.task.md +57 -0
- package/tasks/ask-project-scope-of-work.task.md +57 -0
- package/tasks/ask-project-type.task.md +24 -0
- package/tasks/ask-react-target-service.task.md +32 -0
- package/tasks/ask-redis-config.task.md +42 -0
- package/tasks/ask-redis-host.task.md +16 -0
- package/tasks/ask-redis-port.task.md +18 -0
- package/tasks/ask-refactor-type.task.md +26 -0
- package/tasks/ask-requires-auth.task.md +22 -0
- package/tasks/ask-response-mode.task.md +38 -0
- package/tasks/ask-route-description.task.md +20 -0
- package/tasks/ask-route-path.task.md +29 -0
- package/tasks/ask-seed-row-values.task.md +42 -0
- package/tasks/ask-seed-rows-count.task.md +22 -0
- package/tasks/ask-service-description.task.md +16 -0
- package/tasks/ask-service-name.task.md +27 -0
- package/tasks/ask-service-port.task.md +24 -0
- package/tasks/ask-supported-languages.task.md +40 -0
- package/tasks/ask-table-file-number.task.md +36 -0
- package/tasks/ask-table-indexes.task.md +47 -0
- package/tasks/ask-table-name.task.md +32 -0
- package/tasks/ask-table-needs-soft-delete.task.md +29 -0
- package/tasks/ask-table-needs-status.task.md +30 -0
- package/tasks/ask-table-purpose.task.md +28 -0
- package/tasks/ask-table-seed-data.task.md +44 -0
- package/tasks/ask-target-service.task.md +32 -0
- package/tasks/ask-test-type.task.md +20 -0
- package/tasks/ask-validation-library.task.md +38 -0
- package/tasks/detect-repository-state.task.md +92 -0
- package/tasks/generate-app.task.md +146 -0
- package/tasks/generate-common.task.md +330 -0
- package/tasks/generate-constants.task.md +123 -0
- package/tasks/generate-database.task.md +168 -0
- package/tasks/generate-docker-compose.task.md +298 -0
- package/tasks/generate-dockerfile.task.md +126 -0
- package/tasks/generate-dockerignore.task.md +123 -0
- package/tasks/generate-enc-dec-html.task.md +127 -0
- package/tasks/generate-enc-dec-php.task.md +145 -0
- package/tasks/generate-encryption.task.md +159 -0
- package/tasks/generate-fast-defaults.task.md +68 -0
- package/tasks/generate-gitignore.task.md +79 -0
- package/tasks/generate-headerValidator.task.md +377 -0
- package/tasks/generate-ide-configs.task.md +114 -0
- package/tasks/generate-ioRedis.task.md +120 -0
- package/tasks/generate-language-en.task.md +155 -0
- package/tasks/generate-logging.task.md +257 -0
- package/tasks/generate-model.task.md +180 -0
- package/tasks/generate-notification.task.md +251 -0
- package/tasks/generate-package-json.task.md +114 -0
- package/tasks/generate-rateLimiter.task.md +125 -0
- package/tasks/generate-react-api-client.task.md +169 -0
- package/tasks/generate-react-api-handler.task.md +102 -0
- package/tasks/generate-react-app-jsx.task.md +56 -0
- package/tasks/generate-react-dockerfile.task.md +175 -0
- package/tasks/generate-react-env.task.md +58 -0
- package/tasks/generate-react-gitignore.task.md +49 -0
- package/tasks/generate-react-htaccess.task.md +54 -0
- package/tasks/generate-react-index-html.task.md +53 -0
- package/tasks/generate-react-index-jsx.task.md +51 -0
- package/tasks/generate-react-package-json.task.md +77 -0
- package/tasks/generate-react-welcome-page.task.md +71 -0
- package/tasks/generate-readme.task.md +160 -0
- package/tasks/generate-response.task.md +202 -0
- package/tasks/generate-route-manager.task.md +173 -0
- package/tasks/generate-route.task.md +203 -0
- package/tasks/generate-swagger.task.md +290 -0
- package/tasks/generate-tbl-user-deviceinfo.task.md +75 -0
- package/tasks/generate-template.task.md +129 -0
- package/tasks/generate-validator.task.md +122 -0
- package/tasks/show-db-table-summary.task.md +66 -0
- package/tasks/show-final-summary.task.md +108 -0
- package/tasks/show-init-summary.task.md +257 -0
- package/tasks/write-context.task.md +314 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: generate-enc-dec-html
|
|
4
|
+
agent: nodejs-agent
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# File: enc_dec.html
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
A standalone browser-based tool for testing AES-256-CBC encryption and
|
|
11
|
+
decryption using the exact same KEY and IV configured for this service.
|
|
12
|
+
Used exclusively by developers during development and debugging to
|
|
13
|
+
manually encrypt values before sending them as API request bodies, or
|
|
14
|
+
to decrypt API responses for inspection. This file is gitignored and
|
|
15
|
+
never served by the Express app.
|
|
16
|
+
|
|
17
|
+
Only generated when `client_type == "reactjs"`. Not generated for
|
|
18
|
+
`client_type == "app"`.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Key Detail — Pre-filled KEY and IV
|
|
23
|
+
|
|
24
|
+
This is the most important aspect of this file. The KEY and IV values
|
|
25
|
+
hardcoded into the JavaScript must be the exact values from
|
|
26
|
+
`context.current_init.encryption_key` and
|
|
27
|
+
`context.current_init.encryption_iv` collected during
|
|
28
|
+
`@initialize-project`.
|
|
29
|
+
|
|
30
|
+
The agent reads these values from context and writes them literally into
|
|
31
|
+
the JavaScript functions. Every time this file is generated it will have
|
|
32
|
+
the correct credentials for this specific service instance. This is what
|
|
33
|
+
makes the tool useful — the developer does not need to manually copy keys.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## HTML Structure
|
|
38
|
+
|
|
39
|
+
Single HTML file. No external CSS files. No server-side logic. All
|
|
40
|
+
styling is inline in a style block in head.
|
|
41
|
+
|
|
42
|
+
### Head section
|
|
43
|
+
- `<title>` — use `<service_name> — Encryption & Decryption` where
|
|
44
|
+
service_name comes from `context.current_init.service_name`
|
|
45
|
+
- Load crypto-js from CDN:
|
|
46
|
+
`https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.2.0/crypto-js.min.js`
|
|
47
|
+
This is loaded as a script tag before the closing body tag.
|
|
48
|
+
|
|
49
|
+
### Body section layout
|
|
50
|
+
- `<h1>` heading: `<SERVICE_NAME> — CryptoJS Encryption & Decryption`
|
|
51
|
+
using the service name from context in uppercase.
|
|
52
|
+
- A `<label>` for the input area with text "Plaintext / Ciphertext:"
|
|
53
|
+
- A `<textarea>` with id `"plaintext"`, 10 rows, 100 cols.
|
|
54
|
+
- Two `<button>` elements:
|
|
55
|
+
- First button: text "Encrypt", calls `encrypt()` on click
|
|
56
|
+
- Second button: text "Decrypt", calls `decrypt()` on click
|
|
57
|
+
- A "Clear" button that clears the textarea and both result divs.
|
|
58
|
+
- Two result boxes each with a visible border, padding, and
|
|
59
|
+
`overflow-wrap: break-word` so long cipher strings don't overflow:
|
|
60
|
+
- Box 1: heading "Encrypted Data:", result div with id `"encryptedData"`
|
|
61
|
+
- Box 2: heading "Decrypted Data:", result div with id `"decryptedData"`
|
|
62
|
+
|
|
63
|
+
### CSS (inline in head style block)
|
|
64
|
+
- Buttons: background color `#9c8cc3`, font-weight 800, padding 10px,
|
|
65
|
+
border-radius 5px. Cursor pointer.
|
|
66
|
+
- Result boxes (class `box`): border `1px solid black`, padding 5px,
|
|
67
|
+
margin-top 25px, `overflow-wrap: break-word`.
|
|
68
|
+
- Body: font-family sans-serif, padding 20px, max-width 900px.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## JavaScript Functions
|
|
73
|
+
|
|
74
|
+
All functions are in a single script block before the closing body tag,
|
|
75
|
+
after the crypto-js CDN script tag.
|
|
76
|
+
|
|
77
|
+
### Module-level key constants
|
|
78
|
+
At the top of the script block, define the KEY and IV as constants.
|
|
79
|
+
These are the pre-filled values from context:
|
|
80
|
+
```
|
|
81
|
+
const ENCRYPTION_KEY = CryptoJS.enc.Utf8.parse("<context.current_init.encryption_key>");
|
|
82
|
+
const ENCRYPTION_IV = CryptoJS.enc.Utf8.parse("<context.current_init.encryption_iv>");
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Both parsed using `CryptoJS.enc.Utf8.parse` — consistent with how
|
|
86
|
+
`utilities/encryption.js` parses them for `client_type == "reactjs"`.
|
|
87
|
+
|
|
88
|
+
### encrypt()
|
|
89
|
+
1. Clear the decryptedData div.
|
|
90
|
+
2. Read value from the plaintext textarea. Store as `plaintext`.
|
|
91
|
+
3. Clear the plaintext textarea.
|
|
92
|
+
4. If plaintext is empty — alert "Please enter text to encrypt." Return.
|
|
93
|
+
5. Call `CryptoJS.AES.encrypt(plaintext, ENCRYPTION_KEY, { iv: ENCRYPTION_IV })`.
|
|
94
|
+
Call `.toString()` on the result to get the Base64 cipher string.
|
|
95
|
+
6. Display the cipher string in the encryptedData div.
|
|
96
|
+
|
|
97
|
+
### decrypt()
|
|
98
|
+
1. Clear the encryptedData div.
|
|
99
|
+
2. Read value from the plaintext textarea. Store as `ciphertext`.
|
|
100
|
+
3. Clear the plaintext textarea.
|
|
101
|
+
4. If ciphertext is empty — alert "Please enter ciphertext to decrypt." Return.
|
|
102
|
+
5. Strip surrounding double-quote characters from ciphertext using:
|
|
103
|
+
`ciphertext.replace(/^"(.*)"$/, '$1')`
|
|
104
|
+
This handles the case where the developer pastes a JSON-encoded
|
|
105
|
+
string that has surrounding quotes.
|
|
106
|
+
6. Call `CryptoJS.AES.decrypt(ciphertext, ENCRYPTION_KEY, { iv: ENCRYPTION_IV })`.
|
|
107
|
+
Call `.toString(CryptoJS.enc.Utf8)` to get the plaintext string.
|
|
108
|
+
7. If the result is empty string — display "Decryption failed. Check
|
|
109
|
+
that the input is a valid cipher string." in the decryptedData div.
|
|
110
|
+
Return.
|
|
111
|
+
8. Display the decrypted string in the decryptedData div.
|
|
112
|
+
|
|
113
|
+
### clearAll()
|
|
114
|
+
1. Set textarea value to empty string.
|
|
115
|
+
2. Set encryptedData div innerText to empty string.
|
|
116
|
+
3. Set decryptedData div innerText to empty string.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## What This File Does NOT Do
|
|
121
|
+
|
|
122
|
+
- Does not make any HTTP requests
|
|
123
|
+
- Does not import or use any Node.js modules
|
|
124
|
+
- Does not connect to the service in any way
|
|
125
|
+
- Does not store or transmit the KEY or IV anywhere
|
|
126
|
+
- Does not handle files or binary data — text only
|
|
127
|
+
- Is never served by Express — opened directly in browser by developer
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: generate-enc-dec-php
|
|
4
|
+
agent: nodejs-agent
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# File: enc_dec.php
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
A PHP-based tool for testing AES-256-CBC encryption and decryption using
|
|
11
|
+
the exact same KEY and IV configured for this service. Used exclusively
|
|
12
|
+
by developers during development. Runs as a PHP web page — the developer
|
|
13
|
+
opens it in a browser via a local PHP server or any server with PHP
|
|
14
|
+
installed. This file is gitignored and never part of the Node.js app.
|
|
15
|
+
|
|
16
|
+
Only generated when `client_type == "app"`. Not generated for
|
|
17
|
+
`client_type == "reactjs"`.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Key Detail — Pre-filled KEY and IV
|
|
22
|
+
|
|
23
|
+
Same principle as enc_dec.html. The KEY and IV hardcoded into the PHP
|
|
24
|
+
must be the exact values from `context.current_init.encryption_key` and
|
|
25
|
+
`context.current_init.encryption_iv`.
|
|
26
|
+
|
|
27
|
+
The cryptlib PHP equivalent uses `openssl_encrypt` and `openssl_decrypt`
|
|
28
|
+
with AES-256-CBC. The key must be hashed with SHA-256 first to produce
|
|
29
|
+
a 32-byte key — this is how cryptlib derives its key from the raw KEY
|
|
30
|
+
string, and the PHP side must match exactly.
|
|
31
|
+
|
|
32
|
+
Key derivation in PHP:
|
|
33
|
+
`$secret = hash('sha256', '<context.current_init.encryption_key>')`
|
|
34
|
+
|
|
35
|
+
IV used directly as a plain string:
|
|
36
|
+
`$iv = '<context.current_init.encryption_iv>'`
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## File Structure
|
|
41
|
+
|
|
42
|
+
The file is a single `.php` file that contains both HTML and PHP. The
|
|
43
|
+
HTML form renders first, then the PHP at the bottom processes the
|
|
44
|
+
submitted form and outputs results below the form.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## HTML Section (before closing body tag)
|
|
49
|
+
|
|
50
|
+
### Head section
|
|
51
|
+
- `<meta charset="utf-8">`
|
|
52
|
+
- `<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">`
|
|
53
|
+
- `<title>` — `<service_name> — Encryption & Decryption` using service
|
|
54
|
+
name from context.
|
|
55
|
+
- CSS style block with:
|
|
56
|
+
- Body: font-family sans-serif, padding 20px, max-width 900px
|
|
57
|
+
- `#container`: max-width 900px, margin auto
|
|
58
|
+
- Labels: font-weight bold
|
|
59
|
+
- Textarea: width 100%, box-sizing border-box
|
|
60
|
+
- Submit buttons: padding 8px 16px, cursor pointer, margin-right 8px
|
|
61
|
+
- Result headings: cursor pointer, color #333, font-size 16px
|
|
62
|
+
- Result paragraphs: background #f5f5f5, padding 10px, word-break
|
|
63
|
+
break-all, border 1px solid #ddd
|
|
64
|
+
|
|
65
|
+
### Body section
|
|
66
|
+
- `<div id="container">`
|
|
67
|
+
- `<h1>` heading: `<SERVICE_NAME> — Encryption & Decryption`
|
|
68
|
+
- `<div id="body">`
|
|
69
|
+
- HTML form with:
|
|
70
|
+
- `action="enc_dec.php"` method POST
|
|
71
|
+
- `enctype="multipart/form-data"`
|
|
72
|
+
- Label: "Text or Ciphertext"
|
|
73
|
+
- Textarea: `name="data"`, `id="data"`, `required`, 90 cols, 10 rows
|
|
74
|
+
- Submit button: `name="type"` `value="encrypt"` — text "Encrypt"
|
|
75
|
+
- Submit button: `name="type"` `value="decrypt"` — text "Decrypt"
|
|
76
|
+
- Reset button: `name="reset"` `value="Clear"` — text "Clear"
|
|
77
|
+
|
|
78
|
+
### JavaScript section (before closing body tag)
|
|
79
|
+
Two JavaScript functions for click-to-copy functionality:
|
|
80
|
+
|
|
81
|
+
`CopyToClipboard(containerid)`:
|
|
82
|
+
Handles both IE (document.selection) and modern browsers
|
|
83
|
+
(window.getSelection). Selects the content of the element with the
|
|
84
|
+
given id and executes the browser copy command.
|
|
85
|
+
|
|
86
|
+
`clearContents(containerid)`:
|
|
87
|
+
Sets the value of the element with the given id to empty string.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## PHP Section (after closing html tag)
|
|
92
|
+
|
|
93
|
+
The PHP block processes the form submission. It runs after the HTML
|
|
94
|
+
has been sent to the browser.
|
|
95
|
+
|
|
96
|
+
### Constants
|
|
97
|
+
```
|
|
98
|
+
$encryptionMethod = 'AES-256-CBC';
|
|
99
|
+
$secret = hash('sha256', '<context.current_init.encryption_key>');
|
|
100
|
+
$iv = '<context.current_init.encryption_iv>';
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Note on key derivation: `hash('sha256', key)` produces a 64-character
|
|
104
|
+
hex string. PHP's `openssl_encrypt` with AES-256 requires a 32-byte
|
|
105
|
+
key. When passing a hex string, openssl uses the raw bytes — which for
|
|
106
|
+
a 64-char hex string gives 32 bytes. This is the correct behavior and
|
|
107
|
+
matches how cryptlib derives its key via `getHashSha256`.
|
|
108
|
+
|
|
109
|
+
### Form processing
|
|
110
|
+
Check: `isset($_REQUEST['type']) && isset($_REQUEST['data']) && $_REQUEST['data'] != ''`
|
|
111
|
+
|
|
112
|
+
If not set or empty — output nothing. The page just shows the form.
|
|
113
|
+
|
|
114
|
+
**If type == "encrypt"**:
|
|
115
|
+
1. Trim the input: `$plaintext = trim($_REQUEST['data'])`
|
|
116
|
+
2. Encrypt: `$encrypt_value = openssl_encrypt($plaintext, $encryptionMethod, $secret, 0, $iv)`
|
|
117
|
+
3. Output a result div containing:
|
|
118
|
+
- `<h2>` with `onclick="CopyToClipboard('p1')"` — text "COPY ENCRYPTED"
|
|
119
|
+
- `<p id="p1">` — the encrypted value wrapped in `htmlspecialchars()`
|
|
120
|
+
- `<h2>` with `onclick="CopyToClipboard('p2')"` — text "COPY ORIGINAL"
|
|
121
|
+
- `<p id="p2">` — the original input wrapped in `htmlspecialchars()`
|
|
122
|
+
|
|
123
|
+
**If type == "decrypt"**:
|
|
124
|
+
1. Get ciphertext: `$enc = $_REQUEST['data']`
|
|
125
|
+
2. Decrypt: `$decrypt_value = openssl_decrypt($enc, $encryptionMethod, $secret, 0, $iv)`
|
|
126
|
+
3. Attempt JSON decode: `json_decode($decrypt_value)`
|
|
127
|
+
4. Output a result div containing:
|
|
128
|
+
- `<h2>` with `onclick="CopyToClipboard('p1')"` — text "COPY ENCRYPTED"
|
|
129
|
+
- `<p id="p1">` — the original cipher input wrapped in `htmlspecialchars()`
|
|
130
|
+
- `<h2>` with `onclick="CopyToClipboard('p2')"` — text "COPY DECRYPTED"
|
|
131
|
+
- `<p id="p2">` — the decrypted value wrapped in `htmlspecialchars()`
|
|
132
|
+
- `<h2>` — text "JSON PARSED"
|
|
133
|
+
- `<pre>` — `htmlspecialchars(print_r(json_decode($decrypt_value), true))`
|
|
134
|
+
This shows the decoded JSON structure if the decrypted value is
|
|
135
|
+
valid JSON, making it easy to inspect API response structures.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## What This File Does NOT Do
|
|
140
|
+
|
|
141
|
+
- Does not connect to the Node.js service
|
|
142
|
+
- Does not use any PHP libraries beyond built-in openssl functions
|
|
143
|
+
- Does not store or log any encrypted or decrypted values
|
|
144
|
+
- Is not part of the Node.js application in any way
|
|
145
|
+
- Is never required or imported by any JS file
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: generate-encryption
|
|
4
|
+
agent: nodejs-agent
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# File: utilities/encryption.js
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
Single source of truth for all encryption and decryption operations in the
|
|
11
|
+
service. All other files that need to encrypt or decrypt call this module.
|
|
12
|
+
No other file in the service imports crypto-js or cryptlib directly.
|
|
13
|
+
The active library is determined once at module load from context — the
|
|
14
|
+
rest of the codebase never needs to know which library is active.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Dependencies to Import
|
|
19
|
+
|
|
20
|
+
Read `context.services[<name>].client_type` to determine which library
|
|
21
|
+
to import:
|
|
22
|
+
|
|
23
|
+
- If `client_type == "reactjs"`:
|
|
24
|
+
Import `crypto-js` as `CryptoJS`
|
|
25
|
+
|
|
26
|
+
- If `client_type == "app"`:
|
|
27
|
+
Import `cryptlib`
|
|
28
|
+
|
|
29
|
+
No other crypto imports. Never import both.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Module-Level Constants
|
|
34
|
+
|
|
35
|
+
### key
|
|
36
|
+
Derived once at module load from `process.env.KEY`.
|
|
37
|
+
|
|
38
|
+
- If `client_type == "reactjs"`:
|
|
39
|
+
Parse using `CryptoJS.enc.Utf8.parse(process.env.KEY)`.
|
|
40
|
+
Result is a CryptoJS WordArray. Store as `key`.
|
|
41
|
+
|
|
42
|
+
- If `client_type == "app"`:
|
|
43
|
+
Derive using `cryptlib.getHashSha256(process.env.KEY, 32)`.
|
|
44
|
+
Result is a 32-byte derived key string. Store as `key`.
|
|
45
|
+
|
|
46
|
+
### iv
|
|
47
|
+
Derived once at module load from `process.env.IV`.
|
|
48
|
+
|
|
49
|
+
- If `client_type == "reactjs"`:
|
|
50
|
+
Parse using `CryptoJS.enc.Utf8.parse(process.env.IV)`.
|
|
51
|
+
Result is a CryptoJS WordArray. Store as `iv`.
|
|
52
|
+
|
|
53
|
+
- If `client_type == "app"`:
|
|
54
|
+
Use `process.env.IV` directly as a plain string. Store as `iv`.
|
|
55
|
+
|
|
56
|
+
Both `key` and `iv` are module-level constants. They are never re-derived
|
|
57
|
+
on each function call. If `.env` values are missing at startup the module
|
|
58
|
+
will fail at load time — this is intentional and correct behavior.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Functions
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
### encrypt(data)
|
|
67
|
+
|
|
68
|
+
**Purpose**: Takes any JavaScript value, serializes it, and returns an
|
|
69
|
+
AES-256-CBC encrypted cipher string. Called by `response.js` when
|
|
70
|
+
`ENCRYPTED_TRANSPORT` is true, and by any model function that needs to
|
|
71
|
+
encrypt a value before storing (e.g. passwords).
|
|
72
|
+
|
|
73
|
+
**Parameters**:
|
|
74
|
+
- `data` — any value: object, array, string, number. Never assume type.
|
|
75
|
+
|
|
76
|
+
**Flow**:
|
|
77
|
+
|
|
78
|
+
1. Call `JSON.stringify(data)` to serialize the input to a string.
|
|
79
|
+
This handles all types uniformly including nested objects and arrays.
|
|
80
|
+
|
|
81
|
+
2. Encrypt the serialized string:
|
|
82
|
+
|
|
83
|
+
- If `client_type == "reactjs"`:
|
|
84
|
+
Call `CryptoJS.AES.encrypt(serialized, key, { iv, mode: CryptoJS.mode.CBC })`.
|
|
85
|
+
Call `.toString()` on the result to get the Base64 cipher string.
|
|
86
|
+
|
|
87
|
+
- If `client_type == "app"`:
|
|
88
|
+
Call `cryptlib.encrypt(serialized, key, iv)`.
|
|
89
|
+
Result is already a string.
|
|
90
|
+
|
|
91
|
+
3. Return the cipher string.
|
|
92
|
+
|
|
93
|
+
4. This function is synchronous. Do not make it async — there is no I/O.
|
|
94
|
+
Callers that use await on it will still work, but the function itself
|
|
95
|
+
should not be declared async.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
### decrypt(cipherText)
|
|
100
|
+
|
|
101
|
+
**Purpose**: Takes an AES-256-CBC cipher string and returns the original
|
|
102
|
+
JavaScript value. Called by `headerValidator.js` for API key, token, and
|
|
103
|
+
request body decryption. Called by any route that receives encrypted input.
|
|
104
|
+
|
|
105
|
+
**Parameters**:
|
|
106
|
+
- `cipherText` — encrypted string produced by `encrypt()` or by the
|
|
107
|
+
client-side counterpart (crypto-js in browser or cryptlib in app).
|
|
108
|
+
|
|
109
|
+
**Flow**:
|
|
110
|
+
|
|
111
|
+
1. Validate input: if `cipherText` is null, undefined, empty string, or
|
|
112
|
+
not a string type — return `null` immediately without attempting
|
|
113
|
+
decryption. Do not throw.
|
|
114
|
+
|
|
115
|
+
2. Decrypt the cipher string:
|
|
116
|
+
|
|
117
|
+
- If `client_type == "reactjs"`:
|
|
118
|
+
Call `CryptoJS.AES.decrypt(cipherText, key, { iv, mode: CryptoJS.mode.CBC })`.
|
|
119
|
+
Call `.toString(CryptoJS.enc.Utf8)` on the result to get the
|
|
120
|
+
plain UTF-8 string.
|
|
121
|
+
|
|
122
|
+
- If `client_type == "app"`:
|
|
123
|
+
Call `cryptlib.decrypt(cipherText, key, iv)`.
|
|
124
|
+
Result is a plain string.
|
|
125
|
+
|
|
126
|
+
3. Call `JSON.parse()` on the decrypted string to restore the original
|
|
127
|
+
JavaScript value.
|
|
128
|
+
|
|
129
|
+
4. Return the parsed value.
|
|
130
|
+
|
|
131
|
+
5. Wrap steps 2–4 in a try/catch. On any error — return `null`.
|
|
132
|
+
Never throw from this function. Callers check for null return.
|
|
133
|
+
Never log inside this function — logging is the caller's responsibility.
|
|
134
|
+
|
|
135
|
+
6. This function is synchronous. Do not make it async.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Export
|
|
140
|
+
```
|
|
141
|
+
module.exports = { encrypt, decrypt }
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
No default export. Named exports only. Every file that imports this
|
|
145
|
+
module destructures exactly what it needs:
|
|
146
|
+
`const { encrypt, decrypt } = require('../utilities/encryption')`
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## What This File Does NOT Do
|
|
151
|
+
|
|
152
|
+
- Does not read `req` or `res` — no Express objects
|
|
153
|
+
- Does not log — callers handle logging
|
|
154
|
+
- Does not throw — returns null on failure
|
|
155
|
+
- Does not conditionally skip encryption based on ENCRYPTED_TRANSPORT —
|
|
156
|
+
that decision belongs to `response.js`. This file always encrypts
|
|
157
|
+
when called.
|
|
158
|
+
- Does not import both crypto libraries — only the one matching
|
|
159
|
+
client_type is imported
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: generate-fast-defaults
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
This task auto-populates all non-essential context values silently
|
|
7
|
+
when `context.current_init.init_mode == "fast"`. It runs after the
|
|
8
|
+
essential questions are collected and before show-init-summary.
|
|
9
|
+
|
|
10
|
+
This task only runs for `project_type == "nodejs"`.
|
|
11
|
+
For `project_type == "reactjs"` — security values are inherited from
|
|
12
|
+
the linked backend via ask-linked-service and are never generated here.
|
|
13
|
+
The port and package defaults below still apply to reactjs.
|
|
14
|
+
|
|
15
|
+
## Values to Auto-Generate
|
|
16
|
+
|
|
17
|
+
### Database Config (nodejs only, if not already set)
|
|
18
|
+
- `context.db.host` → set to `"localhost"` if not already in context
|
|
19
|
+
- `context.db.port` → set based on `context.db.type`:
|
|
20
|
+
- postgresql → `5432`
|
|
21
|
+
- mysql → `3306`
|
|
22
|
+
- mongodb → `27017`
|
|
23
|
+
|
|
24
|
+
### Service Port
|
|
25
|
+
- Scan all port values in `context.services`
|
|
26
|
+
- Find the highest port currently in use
|
|
27
|
+
- Set `context.current_init.port` → highest + 1
|
|
28
|
+
- If no services exist yet → set to `1001`
|
|
29
|
+
- Ensure the result does not conflict with any existing port
|
|
30
|
+
|
|
31
|
+
### Package Info
|
|
32
|
+
- `context.current_init.package_name` → same value as
|
|
33
|
+
`context.current_init.service_name`
|
|
34
|
+
- `context.current_init.author` → empty string `""`
|
|
35
|
+
|
|
36
|
+
### Security Values (nodejs only — never run for reactjs)
|
|
37
|
+
Generate all three using cryptographically random characters from the
|
|
38
|
+
set: `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`
|
|
39
|
+
|
|
40
|
+
- `context.current_init.api_key` → 32 random characters
|
|
41
|
+
- `context.current_init.encryption_key` → exactly 32 random characters
|
|
42
|
+
- `context.current_init.encryption_iv` → first 16 characters of
|
|
43
|
+
`context.current_init.encryption_key`
|
|
44
|
+
Always derived from the key — never randomly generated.
|
|
45
|
+
Since encryption_key is always 32 characters, the first 16
|
|
46
|
+
characters are always exactly 16. No separate validation needed.
|
|
47
|
+
|
|
48
|
+
Validate after generation:
|
|
49
|
+
- encryption_key must be exactly 32 characters — regenerate if not
|
|
50
|
+
- encryption_iv must equal the first 16 characters of encryption_key —
|
|
51
|
+
re-derive if not
|
|
52
|
+
|
|
53
|
+
### Redis Config (nodejs only — skip for reactjs)
|
|
54
|
+
- `context.current_init.redis_host` → `"localhost"`
|
|
55
|
+
- `context.current_init.redis_port` → `6379`
|
|
56
|
+
|
|
57
|
+
## Important Rules
|
|
58
|
+
|
|
59
|
+
- Never overwrite a value that was already explicitly set by a
|
|
60
|
+
previous ask-* task in this session.
|
|
61
|
+
- Check each key before setting: if it already has a non-empty value
|
|
62
|
+
in `context.current_init` → skip it.
|
|
63
|
+
- This task is silent — it does not print anything to the user.
|
|
64
|
+
All auto-generated values will be visible in show-init-summary
|
|
65
|
+
where the user can review and change them.
|
|
66
|
+
|
|
67
|
+
Do not ask any question. Do not produce any output.
|
|
68
|
+
Store all values and return.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: generate-gitignore
|
|
4
|
+
agent: nodejs-agent
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# File: .gitignore
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
Defines which files and directories Git should never track. Generated
|
|
11
|
+
once during `@initialize-project`. Ensures sensitive files (env,
|
|
12
|
+
keys, credentials), generated files (node_modules, logs), and
|
|
13
|
+
development tools (demo encryption files) are never committed.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Contents
|
|
18
|
+
|
|
19
|
+
### Always include (every NodeJS service)
|
|
20
|
+
```
|
|
21
|
+
# Dependencies
|
|
22
|
+
node_modules/
|
|
23
|
+
|
|
24
|
+
# Environment variables
|
|
25
|
+
.env
|
|
26
|
+
|
|
27
|
+
# RSA keys and credentials
|
|
28
|
+
pem/
|
|
29
|
+
|
|
30
|
+
# Uploaded files and static assets
|
|
31
|
+
images/
|
|
32
|
+
|
|
33
|
+
# Log files
|
|
34
|
+
logger/logs/
|
|
35
|
+
|
|
36
|
+
# OS files
|
|
37
|
+
.DS_Store
|
|
38
|
+
Thumbs.db
|
|
39
|
+
|
|
40
|
+
# IDE files
|
|
41
|
+
.vscode/
|
|
42
|
+
.idea/
|
|
43
|
+
*.swp
|
|
44
|
+
*.swo
|
|
45
|
+
|
|
46
|
+
# codeninja MCP server dependencies (auto-installed by codeninja init)
|
|
47
|
+
.codeninja/node_modules/
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Include when `client_type == "reactjs"`
|
|
51
|
+
```
|
|
52
|
+
# Encryption demo tool
|
|
53
|
+
enc_dec.html
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Include when `client_type == "app"`
|
|
57
|
+
```
|
|
58
|
+
# Encryption demo tool
|
|
59
|
+
enc_dec.php
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Include when `client_type == "app"` (Firebase credentials)
|
|
63
|
+
```
|
|
64
|
+
# Firebase service account
|
|
65
|
+
pem/service-file.json
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Note: `pem/` already covers this since the whole directory is ignored,
|
|
69
|
+
but the explicit line makes the intent clear to developers.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## What This File Does NOT Do
|
|
74
|
+
|
|
75
|
+
- Does not ignore `.env.example` — that file should be committed
|
|
76
|
+
so other developers know what variables are needed
|
|
77
|
+
- Does not ignore test files
|
|
78
|
+
- Does not ignore the document/ swagger folder
|
|
79
|
+
- Does not ignore database migration files
|