@rubytech/create-maxy 1.0.697 → 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.
- package/package.json +1 -1
- package/payload/platform/neo4j/migrations/002-linkedin-types.cypher +103 -0
- package/payload/platform/plugins/docs/references/platform.md +1 -1
- package/payload/platform/plugins/docs/references/troubleshooting.md +28 -0
- package/payload/server/chunk-3VVHVJK2.js +11405 -0
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/assets/{admin-BsLm49w9.js → admin-CjRb2gH7.js} +1 -1
- package/payload/server/public/assets/{data-BKexd229.js → data-sqtkLfgS.js} +1 -1
- package/payload/server/public/assets/{file-DZkqmm8M.js → file-Dsaxvh3t.js} +1 -1
- package/payload/server/public/assets/{graph-CPqHYozW.js → graph-ih5hzKOO.js} +1 -1
- package/payload/server/public/assets/{house-CPxWBrMl.js → house-Bse5AWrO.js} +1 -1
- package/payload/server/public/assets/{jsx-runtime-2yRmkrVq.css → jsx-runtime-DDu3Iu4h.css} +1 -1
- package/payload/server/public/assets/public-Btb8pJWN.js +5 -0
- package/payload/server/public/assets/{share-2-Bauv6ctA.js → share-2-nB3FxYbd.js} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-BTEcf6H3.js → useVoiceRecorder-D2OAQlJy.js} +3 -3
- package/payload/server/public/assets/{x-Kc93nSru.js → x-g2pNE8fh.js} +1 -1
- package/payload/server/public/data.html +6 -6
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +7 -7
- package/payload/server/public/public.html +4 -4
- package/payload/server/server.js +70 -26
- package/payload/server/public/assets/public-BthX_YNC.js +0 -5
- /package/payload/server/public/assets/{jsx-runtime-7o3Lvx89.js → jsx-runtime-rRO5uNvZ.js} +0 -0
package/package.json
CHANGED
|
@@ -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.
|