@rubytech/create-maxy 1.0.696 → 1.0.698

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.
Files changed (23) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/neo4j/migrations/002-linkedin-types.cypher +103 -0
  3. package/payload/platform/plugins/docs/references/platform.md +1 -1
  4. package/payload/platform/plugins/docs/references/troubleshooting.md +28 -0
  5. package/payload/server/chunk-3VVHVJK2.js +11405 -0
  6. package/payload/server/maxy-edge.js +1 -1
  7. package/payload/server/public/assets/{admin-BZSstsyc.js → admin-CjRb2gH7.js} +1 -1
  8. package/payload/server/public/assets/{data-BKexd229.js → data-sqtkLfgS.js} +1 -1
  9. package/payload/server/public/assets/{file-DZkqmm8M.js → file-Dsaxvh3t.js} +1 -1
  10. package/payload/server/public/assets/{graph-CPqHYozW.js → graph-ih5hzKOO.js} +1 -1
  11. package/payload/server/public/assets/{house-CPxWBrMl.js → house-Bse5AWrO.js} +1 -1
  12. package/payload/server/public/assets/{jsx-runtime-2yRmkrVq.css → jsx-runtime-DDu3Iu4h.css} +1 -1
  13. package/payload/server/public/assets/public-Btb8pJWN.js +5 -0
  14. package/payload/server/public/assets/{share-2-Bauv6ctA.js → share-2-nB3FxYbd.js} +1 -1
  15. package/payload/server/public/assets/{useVoiceRecorder-BTEcf6H3.js → useVoiceRecorder-D2OAQlJy.js} +3 -3
  16. package/payload/server/public/assets/{x-Kc93nSru.js → x-g2pNE8fh.js} +1 -1
  17. package/payload/server/public/data.html +6 -6
  18. package/payload/server/public/graph.html +6 -6
  19. package/payload/server/public/index.html +7 -7
  20. package/payload/server/public/public.html +4 -4
  21. package/payload/server/server.js +70 -26
  22. package/payload/server/public/assets/public-BthX_YNC.js +0 -5
  23. /package/payload/server/public/assets/{jsx-runtime-7o3Lvx89.js → jsx-runtime-rRO5uNvZ.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-maxy",
3
- "version": "1.0.696",
3
+ "version": "1.0.698",
4
4
  "description": "Install Maxy — AI for Productive People",
5
5
  "bin": {
6
6
  "create-maxy": "./dist/index.js"
@@ -0,0 +1,103 @@
1
+ // ============================================================
2
+ // Migration 002 — LinkedIn import node types
3
+ // Adds the labels required to accommodate a full LinkedIn
4
+ // Basic Data Export. Idempotent: every statement uses
5
+ // IF NOT EXISTS so the migration can be re-run safely.
6
+ // ============================================================
7
+
8
+ // ----------------------------------------------------------
9
+ // Organization — schema:Organization. LinkedIn companies that
10
+ // connections work for, that Joel has held positions at, that
11
+ // he follows, or that appear as recommendation subjects.
12
+ // Distinct from :LocalBusiness (the Maxy account itself).
13
+ //
14
+ // Natural key: (accountId, nameNormalised) — lowercased,
15
+ // whitespace-trimmed company name. LinkedIn export has no
16
+ // stable organization id in the basic archive, so dedupe on
17
+ // normalised display name.
18
+ // ----------------------------------------------------------
19
+ CREATE CONSTRAINT organization_account_name_unique IF NOT EXISTS
20
+ FOR (o:Organization) REQUIRE (o.accountId, o.nameNormalised) IS UNIQUE;
21
+
22
+ CREATE INDEX organization_account IF NOT EXISTS
23
+ FOR (o:Organization) ON (o.accountId);
24
+
25
+ CREATE VECTOR INDEX organization_embedding IF NOT EXISTS
26
+ FOR (o:Organization) ON (o.embedding)
27
+ OPTIONS {
28
+ indexConfig: {
29
+ `vector.dimensions`: 768,
30
+ `vector.similarity_function`: 'cosine'
31
+ }
32
+ };
33
+
34
+ // ----------------------------------------------------------
35
+ // EducationalOrganization — schema:EducationalOrganization.
36
+ // Schools attended (Education.csv). Separate label (not a
37
+ // sublabel of Organization) so filter chips in /graph keep
38
+ // companies and schools visually distinct. Same natural key
39
+ // shape as Organization.
40
+ // ----------------------------------------------------------
41
+ CREATE CONSTRAINT edu_org_account_name_unique IF NOT EXISTS
42
+ FOR (e:EducationalOrganization) REQUIRE (e.accountId, e.nameNormalised) IS UNIQUE;
43
+
44
+ CREATE INDEX edu_org_account IF NOT EXISTS
45
+ FOR (e:EducationalOrganization) ON (e.accountId);
46
+
47
+ // ----------------------------------------------------------
48
+ // Skill — Joel's declared skills (Skills.csv) and the skills
49
+ // named in endorsement rows. Natural key (accountId,
50
+ // nameNormalised) so "machine learning" and "Machine Learning"
51
+ // collapse to one node.
52
+ // ----------------------------------------------------------
53
+ CREATE CONSTRAINT skill_account_name_unique IF NOT EXISTS
54
+ FOR (s:Skill) REQUIRE (s.accountId, s.nameNormalised) IS UNIQUE;
55
+
56
+ // ----------------------------------------------------------
57
+ // Credential — schema:EducationalOccupationalCredential.
58
+ // Professional certifications (Certifications.csv). Natural
59
+ // key (accountId, name, authority) — a credential is defined
60
+ // by its name and issuing authority.
61
+ // ----------------------------------------------------------
62
+ CREATE CONSTRAINT credential_unique IF NOT EXISTS
63
+ FOR (c:Credential) REQUIRE (c.accountId, c.name, c.authority) IS UNIQUE;
64
+
65
+ // ----------------------------------------------------------
66
+ // Article — schema:Article. Posts Joel authored on LinkedIn
67
+ // (Articles/ directory). Natural key elementId-less: content
68
+ // hash of (title + publishedAt) scoped to account.
69
+ // ----------------------------------------------------------
70
+ CREATE CONSTRAINT article_unique IF NOT EXISTS
71
+ FOR (a:Article) REQUIRE (a.accountId, a.articleHash) IS UNIQUE;
72
+
73
+ // ----------------------------------------------------------
74
+ // Recommendation — schema:Review (recommendation is a
75
+ // specialisation). One row per written-about relationship,
76
+ // direction encoded in edges (GAVE_RECOMMENDATION vs
77
+ // RECEIVED_RECOMMENDATION). Natural key: sha256 of
78
+ // (authorUrl + subjectUrl + creationDate).
79
+ // ----------------------------------------------------------
80
+ CREATE CONSTRAINT recommendation_unique IF NOT EXISTS
81
+ FOR (r:Recommendation) REQUIRE (r.accountId, r.recommendationHash) IS UNIQUE;
82
+
83
+ // ----------------------------------------------------------
84
+ // Sublabels — no new constraints, no new indexes. The
85
+ // existing Conversation / Message constraints apply.
86
+ // :Conversation:LinkedInConversation — messages.csv threads
87
+ // :Message:LinkedInMessage — individual DMs
88
+ // The sublabel is set at CREATE time (set-semantic labels)
89
+ // and drives /graph canvas colour and filter-chip separation
90
+ // without schema fragmentation.
91
+ // ----------------------------------------------------------
92
+
93
+ // ----------------------------------------------------------
94
+ // Person additions — LinkedIn carries two properties that do
95
+ // not already have an index: linkedinUrl (natural key for
96
+ // LinkedIn-origin persons) and isOperator (marks Joel's own
97
+ // Person node so the import can MATCH it from every row).
98
+ // ----------------------------------------------------------
99
+ CREATE INDEX person_linkedin_url IF NOT EXISTS
100
+ FOR (p:Person) ON (p.linkedinUrl);
101
+
102
+ CREATE INDEX person_is_operator IF NOT EXISTS
103
+ FOR (p:Person) ON (p.accountId, p.isOperator);
@@ -52,7 +52,7 @@ The memory graph is stored on your Pi. It never leaves your network.
52
52
 
53
53
  ## The Web Interface
54
54
 
55
- The web app runs on your Pi on port 19200. A small always-on front door (`maxy-edge`) owns that port and the remote terminal transport — so when the Software Update command restarts the app server, the browser-side terminal keeps streaming bytes exactly like an SSH session would. The edge also hosts the update flow's own routes (the sudo prompt, the action launcher, the SSE progress stream, the installed-version poll), so the Software Update modal's log panel does not go blank during the app-server restart window — it keeps receiving lines, heartbeats, and the final exit event unbroken. Login cookies are HMAC-signed with a shared key on disk, so both processes recognise the same session without any coordination and you do not have to log in again after an update. It provides:
55
+ The web app runs on your Pi on port 19200. A small always-on front door (`maxy-edge`) owns that port and the remote terminal transport — so when the Software Update command restarts the app server, the browser-side terminal keeps streaming bytes exactly like an SSH session would. The edge also hosts the update flow's own routes (the sudo prompt, the action launcher, the SSE progress stream, the installed-version poll), so the Software Update modal's log panel does not go blank during the app-server restart window — it keeps receiving lines, heartbeats, and the final exit event unbroken. Login cookies are HMAC-signed with a shared key on disk, so both processes recognise the same session without any coordination and you do not have to log in again after an update. Every request is also classified as LAN or external based on the network shape it arrived on — LAN browsers reach admin directly; the remote password screen only appears on the tunnel-exposed admin domain. It provides:
56
56
 
57
57
  - **Admin chat** (at `/`) — your primary interface, PIN-protected
58
58
  - **Public chat** (at `/{agent-name}`) — visitor-facing agents, each with their own URL. On public hostnames, the root path serves the default agent.
@@ -1,5 +1,33 @@
1
1
  # Troubleshooting
2
2
 
3
+ ## Fresh install opens to "Set your remote password" on the LAN URL
4
+
5
+ **Symptom:** On a brand-new device, the LAN URL printed by `create-maxy` (e.g. `http://maxy.local:19200`) opens to a remote-password setup page instead of admin onboarding. This was a Task-647-era regression and should not occur on any install built after Task 679.
6
+
7
+ **Diagnose:** On the Pi, grep the UI server log for the gate's disambiguation fields:
8
+
9
+ ```
10
+ tail -200 ~/.maxy/logs/maxy-ui.log | rg '\[remote-auth\].*resolvedKind='
11
+ ```
12
+
13
+ - `resolvedKind=lan` on a `login required` or `not configured` line means the classifier sees the request as local — if the browser is still on the remote-auth page, something cached the older page before the fix shipped (hard-refresh the tab).
14
+ - `resolvedKind=external` means the request chain presents as remote (routable IP in the first `x-forwarded-for` hop). On a LAN-only browser this points to a proxy or VPN rewriting headers between the browser and the Pi.
15
+ - `resolvedKind=unknown` is a defect — the classifier could not identify the TCP peer. Capture the log line and file it; do not work around it.
16
+
17
+ **Fix:** If all three fields confirm the LAN shape and the gate still refuses, upgrade the platform (`Software Update` from admin chat) to pick up the Task-679 classifier.
18
+
19
+ ---
20
+
21
+ ## Remote sign-in is rejected with "Remote access requires TLS"
22
+
23
+ **Symptom:** Posting the remote-auth password returns a plain-text `400 Remote access requires TLS` response instead of completing sign-in.
24
+
25
+ **What this means:** The login endpoint will only issue a session cookie when the request arrived over HTTPS (via the Cloudflare tunnel). Browsers silently drop `Set-Cookie: Secure` on plain-HTTP responses, so minting a cookie there would produce a dead-end redirect. Task 679 replaced that silent failure with this loud one.
26
+
27
+ **Fix:** Reach the admin surface through the tunnel hostname (e.g. `https://admin.<your-domain>`), not an IP or plain-HTTP URL. If you need LAN access, use the LAN URL (`http://<hostname>.local:<port>`) — LAN never hits the remote-auth endpoint.
28
+
29
+ ---
30
+
3
31
  ## Agent Not Responding
4
32
 
5
33
  **Symptom:** You send a message and nothing comes back, or the response never arrives.