ecoportal-api-graphql 1.3.14 → 1.3.15

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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/.ai-assistance/projects/TODO.md +170 -118
  3. data/.ai-assistance/skills/ai-instructions/SKILL.md +48 -48
  4. data/.ai-assistance/skills/code-specs/SKILL.md +69 -69
  5. data/.ai-assistance/skills/gemini-assist/SKILL.md +63 -63
  6. data/.ai-assistance/skills/project-cycle/SKILL.md +177 -177
  7. data/.ai-assistance/skills/refactor/SKILL.md +62 -62
  8. data/.ai-assistance/skills/spec-generation/SKILL.md +72 -72
  9. data/.gitlab-ci.yml +64 -12
  10. data/CHANGELOG.md +60 -0
  11. data/changelog.d/fixed-mr51-payload-item-mismatches.md +17 -0
  12. data/lib/ecoportal/api/common/graphql/http_client.rb +6 -0
  13. data/lib/ecoportal/api/graphql/base/ai_summary_version.rb +17 -17
  14. data/lib/ecoportal/api/graphql/base/page/task.rb +24 -0
  15. data/lib/ecoportal/api/graphql/base/page.rb +17 -16
  16. data/lib/ecoportal/api/graphql/base/template.rb +35 -0
  17. data/lib/ecoportal/api/graphql/base.rb +2 -0
  18. data/lib/ecoportal/api/graphql/compat/response.rb +35 -35
  19. data/lib/ecoportal/api/graphql/file_upload/client.rb +21 -10
  20. data/lib/ecoportal/api/graphql/fragment/field_configuration.rb +38 -0
  21. data/lib/ecoportal/api/graphql/fragment/force.rb +14 -10
  22. data/lib/ecoportal/api/graphql/fragment/page_task.rb +39 -0
  23. data/lib/ecoportal/api/graphql/fragment/template.rb +51 -0
  24. data/lib/ecoportal/api/graphql/fragment.rb +3 -0
  25. data/lib/ecoportal/api/graphql/model/page/task.rb +16 -0
  26. data/lib/ecoportal/api/graphql/model/page.rb +16 -15
  27. data/lib/ecoportal/api/graphql/model/template.rb +15 -0
  28. data/lib/ecoportal/api/graphql/model.rb +2 -0
  29. data/lib/ecoportal/api/graphql/mutation/ai_summary/generate.rb +45 -45
  30. data/lib/ecoportal/api/graphql/mutation/ai_summary/submit_feedback.rb +40 -40
  31. data/lib/ecoportal/api/graphql/mutation/page/approve_review_task.rb +40 -40
  32. data/lib/ecoportal/api/graphql/mutation/page/batch_update_review_task.rb +38 -40
  33. data/lib/ecoportal/api/graphql/mutation/page/create_draft.rb +38 -40
  34. data/lib/ecoportal/api/graphql/mutation/page/delete_draft.rb +38 -40
  35. data/lib/ecoportal/api/graphql/mutation/page/execute_force_commands.rb +7 -7
  36. data/lib/ecoportal/api/graphql/mutation/page/execute_workflow_commands.rb +8 -7
  37. data/lib/ecoportal/api/graphql/mutation/page/publish_draft.rb +38 -40
  38. data/lib/ecoportal/api/graphql/mutation/page/reject_review_task.rb +40 -40
  39. data/lib/ecoportal/api/graphql/mutation/page/restart_review_task.rb +40 -40
  40. data/lib/ecoportal/api/graphql/mutation/page/undo_review_task.rb +40 -40
  41. data/lib/ecoportal/api/graphql/mutation/preset_view/destroy.rb +34 -35
  42. data/lib/ecoportal/api/graphql/mutation/register/destroy.rb +35 -35
  43. data/lib/ecoportal/api/graphql/mutation/smart_fill/generate.rb +36 -36
  44. data/lib/ecoportal/api/graphql/mutation/smart_fill/submit_feedback.rb +40 -40
  45. data/lib/ecoportal/api/graphql/mutation/smart_fill.rb +13 -13
  46. data/lib/ecoportal/api/graphql/mutation/template/create_related_page.rb +46 -46
  47. data/lib/ecoportal/api/graphql/mutation/template/destroy_related_page.rb +1 -1
  48. data/lib/ecoportal/api/graphql/mutation/template/update_information.rb +1 -1
  49. data/lib/ecoportal/api/graphql/mutation.rb +20 -20
  50. data/lib/ecoportal/api/graphql/payload/ok_payload.rb +36 -21
  51. data/lib/ecoportal/api/graphql/payload/page/draft.rb +26 -13
  52. data/lib/ecoportal/api/graphql/payload/page/review_task.rb +13 -13
  53. data/lib/ecoportal/api/graphql/payload/page/review_task_batch.rb +23 -0
  54. data/lib/ecoportal/api/graphql/payload/page.rb +20 -19
  55. data/lib/ecoportal/api/graphql/payload/preset_view.rb +15 -11
  56. data/lib/ecoportal/api/graphql/payload/register.rb +15 -11
  57. data/lib/ecoportal/api/graphql/payload/template/create_related_page.rb +1 -1
  58. data/lib/ecoportal/api/graphql/payload/template/destroy_related_page.rb +1 -1
  59. data/lib/ecoportal/api/graphql/payload/template/update_information.rb +1 -1
  60. data/lib/ecoportal/api/graphql/query/page_with_forces.rb +9 -3
  61. data/lib/ecoportal/api/graphql/query/pages_workflow_commands.rb +9 -3
  62. data/lib/ecoportal/api/graphql/query/register_preset_views.rb +78 -78
  63. data/lib/ecoportal/api/graphql.rb +9 -5
  64. data/lib/ecoportal/api/graphql_version.rb +1 -1
  65. data/tests/dump_schema.rb +88 -0
  66. data/tests/validate_queries.rb +34 -12
  67. metadata +11 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5cbeb13326afff8c35946fd492b9bd6cd050e28819497b643bb4ea6c4b41caca
4
- data.tar.gz: ad4660f8fa032e08d0c5f09b199f280d8b42a4e234144ad2fab4041b154fe835
3
+ metadata.gz: 43397010b997d3427eda7b91683044467b679ad72fdea66e910ddf1f8eda6828
4
+ data.tar.gz: 2d1540686b0e07fbf06f56fb2ff922302fee08a35a9370b18794401c66ec50da
5
5
  SHA512:
6
- metadata.gz: 7337308796e0a6800e9dd678d8b9317978d4cf13f6514b2ba95e5d6eaac95b9833be786ca573b7e59613660077aaa78c808a62c4bbef0c9e2f1a08e0c752e857
7
- data.tar.gz: 602edaca4d582eeb876549bba42735fc17fc07d832de713fd3ba84234cc2a876aea876beb51c4fb54eef3faf5a334b889443d922d9c6debe196545389b2715e6
6
+ metadata.gz: 7623eede099dbce829d5b1bba47f775926c5dfdf5e56f1a407514bb68360af8b25c0a83375983b09e4767a52dec947a313859dc2c8cff61f27476a0d703af2ff
7
+ data.tar.gz: a42d2dfec504502bf95a3bbe614c39d3f64499f2996f242d8c48afb325554f542332b9ec4110fb58e61b07ce345a63d30e6193990980b0f68860bbe17baf8cf7
@@ -1,118 +1,170 @@
1
- # Project TODO
2
-
3
- ## Pending
4
-
5
- - [ ] **⏰ CI: query-validation step (DUE by 2026-07-17 — within 2 weeks of 2026-07-03)** — wire
6
- `tests/validate_queries.rb` into CI so the whole class of GraphQL selection bugs fails *before*
7
- release, not in a client runner. **Use a FRESHLY-introspected schema** (do NOT commit the 6.3MB
8
- dump it goes stale); fail the build only on the two structural classes ("field must have
9
- selections" / "selections can't be made on scalars"). Motivated by the 2026-07-03 v1.3.10 hotfix
10
- (LocationStructure `updatedAt`/`createdAt`) those queries had no spec and first broke in prod.
11
- Also: fix the 3 flagged union findings — **TRIAGED 2026-07-03: all THREE are REAL bugs** (verified
12
- by rendering the assembled docs + re-validating fixes; not harness/dump artifacts). Each selects
13
- fields directly on a union (invalid GraphQL) — wrap in the members' shared interface:
14
- - `Query::PageWithForces` (page_with_forces.rb:33-35): bare `forces` on `PageUnion`
15
- `... on BasePageInterface { forces { ...ForceFields } }`. ALSO `fragment ForceFields`
16
- (fragment/force.rb:15,20) selects `id` on `DataFieldBinding`/`SectionBinding` which have NO `id`
17
- (only name/reference/referenceId) → drop `id` (or use `referenceId`).
18
- - `Query::PagesWorkflowCommands` (pages_workflow_commands.rb:33-37): bare `workflow` on `PageUnion`
19
- `... on BasePageInterface { workflow { ... } }`. (The "unused variable" errors were an
20
- artifact a validator cascade from the union error; no action on the vars.)
21
- - `Query::RegisterPresetViews` (register_preset_views.rb:71): bare `{id key name weight}` on
22
- `FieldConfigurationUnion` `... on FieldConfigurationInterface { id key name weight }`.
23
- None of these 3 queries have specs add render/validation specs alongside the fixes. These are
24
- latent (not the users-sync incident); PageWithForces is WIP. Ship as a follow-up patch (1.3.11).
25
-
26
- - [x] **Builder::Register** `createRegister`, `updateRegister`, `destroyRegister` mutations.
27
- `Base::Register`, `Model::Register`, `Input::Register::Create/Update`, `Payload::Register`.
28
- `Builder::Register` with `create`, `update`, `destroy`, and `preset_view` sub-builder.
29
- `GraphQL#register` exposed (singular, distinct from `#registers` compat layer).
30
- *Done 2026-06-08*
31
-
32
- - [ ] **Dashboards / Charts** — `Register.defaultDashboardId` and dashboard queries/mutations
33
- are not yet wrapped. Backend has dashboard configuration tied to registers and organisations.
34
- Scope: `Base::Dashboard` model, `Query::Dashboard(s)`, `Builder::Register#set_default_dashboard`.
35
- Priority: medium needed when scripts need to manage register dashboard configs.
36
-
37
- - [x] **AI field mutations** — `generateAiSummary`, `generateSmartFill`,
38
- `submitAiSummaryFeedback`, `submitSmartFillFeedback` fully wrapped.
39
- `Mutation::AiSummary::Generate/SubmitFeedback`, `Mutation::SmartFill::Generate/SubmitFeedback`,
40
- `Payload::AiSummaryGenerate`, `Payload::OkPayload`, `Base::AiSummaryVersion`.
41
- `Builder::Page` wired: `generate_ai_summary`, `submit_ai_summary_feedback`,
42
- `generate_smart_fill`, `submit_smart_fill_feedback`.
43
- *Done 2026-06-08*
44
-
45
- - [ ] **AI prompt review workflow** AiSummary and SmartFill fields store an `instructions`
46
- field (the AI prompt, template-configured by humans). No audit/review workflow exists.
47
- The gem can read `field.instructions` on AiSummary/SmartFill instances already.
48
- What's needed: a way to scan pages/templates for these instructions and surface them
49
- for review. Possibly: `Query::PagesWithAiFields` + a review report script.
50
- See `.ai-assistance/code/ecoPortal_architecture/13_ai_infrastructure.md` for context.
51
- Priority: low/design — the need is real but the right interface is TBD.
52
-
53
- - [x] **eP Meta AI scaffolding project** — Standalone template repo at
54
- `C:\ruby_scripts\git\ecoPortal_ai_standards`. Bridge protocol, all scripts
55
- (lock-acquire, task-read, task-create, setup-mcps, etc.), all skills, conventions,
56
- integrations, capabilities registry, CLAUDE.md template ({{PLACEHOLDER}} vars),
57
- ONBOARDING.md (15-min setup guide), `init-project.ts` bootstrap script.
58
- Push to GitLab to share: `git@gitlab.ecoportal.co.nz:oscar/ecoPortal_ai_standards.git`
59
- *Done 2026-06-08*
60
-
61
- - [ ] **Commit unstaged changes** Large set of modified files on `ai_dev_process` branch
62
- not yet staged or committed. Review and commit once session is fully restored.
63
-
64
- ## Bridge improvements (from Gemini review 2026-06-04)
65
-
66
- - [x] **Security: Code must prompt before executing bridge-requested shell commands** —
67
- Rule added to `.ai-assistance/bridge/CLAUDE.md` "Running Code non-interactively" section.
68
- Code must surface any shell command to the user before running it, even in
69
- skip-permissions mode. User denial mark task FAILED.
70
- *Done 2026-06-08*
71
-
72
- - [x] **Atomic LOCK acquisition** — `scripts/lock-acquire.sh` implemented.
73
- Uses temp-file + hard-link (atomic on POSIX/NTFS); falls back to bash `noclobber`.
74
- Reports held-by agent/intent on contention. Auto-detects stale locks by mtime.
75
- `bridge/CLAUDE.md` updated to reference it as the preferred acquisition method.
76
- *Done 2026-06-08*
77
-
78
- - [x] **Stale IN_PROGRESS recovery** `bridge-init.sh` updated: scans for IN_PROGRESS
79
- tasks older than 1 hour (via `stat` mtime), reports them in `stale_tasks` + `stale`
80
- count in STATUS JSON. `bridge/CLAUDE.md` updated with Code's required response:
81
- report to user, ask to reset to PENDING or mark FAILED.
82
- *Done 2026-06-08*
83
-
84
- - [x] **`task-read.ts` script** — `scripts/task-read.ts` implemented.
85
- Parses all sections (title, status, created, from, to, context, request, expected,
86
- result, notes) from inbox/outbox/archive files. Searches all bridge dirs automatically.
87
- Output: structured JSON. Saves ~200 tokens per task read vs raw Markdown.
88
- *Done 2026-06-08*
89
-
90
- - [x] **Archive pruning convention** — Documented in `bridge/CLAUDE.md` "Archive pruning"
91
- section: keep last 90 days or last 50 task pairs; git history is the audit trail;
92
- prune manually when folder gets unwieldy.
93
- *Done 2026-06-08*
94
-
95
- ## File upload
96
-
97
- - [ ] **File upload** Support uploading files to attach to `File` and `ImageGallery`
98
- data fields (and potentially Action file attachments at a later stage).
99
- This is distinct from the `attach` operation (which links existing resources to
100
- a target model). Upload requires direct multipart/form-data HTTP to a separate
101
- endpoint before the GraphQL mutation references the resulting file ID.
102
- Scope:
103
- - Identify the upload endpoint and auth pattern (likely REST, not GraphQL)
104
- - Create `HttpClient#upload(file_path:, ...)` or similar
105
- - Create `Input::FileAttachment` to carry the resulting file container ID into mutations
106
- - Wire into data field update inputs (Phase E concern for fields, sooner for Actions)
107
- Priority: Medium — needed before data field updates can be fully functional.
108
- Note: Actions file attachment may be needed sooner — track separately if it becomes urgent.
109
-
110
- ## Completed
111
-
112
- - [x] **Gemini design review of bridge architecture** Done 2026-06-04. Response in
113
- `.ai-assistance/bridge/context/gemini-review-response.md`.
114
- - [x] **Regenerate GitLab PAT** — New token generated, April 2027 expiry, rotation enabled.
115
- Updated in `.env` and documented in `integrations/gitlab-mcp.md`.
116
- - [x] **Rename `.claude/` to `.ai-assistance/`** Done 2026-06-04. All references updated
117
- across scripts, CLAUDE.md, gitignore, and capabilities docs.
118
- - [x] **MCP setup script** — `setup-mcps.ts` + tests written. Teammates run once per machine.
1
+ # Project TODO
2
+
3
+ ## Pending
4
+
5
+ - [x] **CI: query-validation step** (was ⏰ DUE 2026-07-17)`tests/validate_queries.rb` is wired
6
+ into CI as the **blocking** `validate-queries` job. *Done 2026-07-29.*
7
+ - Fresh introspection at pipeline time via the new **`tests/dump_schema.rb`** (env-driven:
8
+ `SERVER` / `ORGANIZATION_ID` / `USER_EMAIL` / `USER_PASS`; `SERVER` is required on purpose
9
+ the gem's default host is PROD). No dump is committed: they go stale, and a stale schema both
10
+ invents noise and hides real findings. `validate_queries.rb` with no argument now resolves the
11
+ newest dump in the (gitignored) `.ai-assistance/tmp/`.
12
+ - **Third failing class added: "can't be made directly on unions."** This is the gap that made the
13
+ original gate insufficient: the 3 union findings landed in the advisory OTHER bucket and needed
14
+ a human to spot them. Selecting on a union without a type condition is invalid under any schema,
15
+ so it is safe to fail on unlike "field doesn't exist", which is staleness-shaped.
16
+ - **All 3 union findings now fixed** (`RegisterPresetViews` on 2026-07-26 via `dc8efc7`;
17
+ `PageWithForces` + `PagesWorkflowCommands` on 2026-07-29 via `... on BasePageInterface`), plus
18
+ the companion `fragment ForceFields` bug (`id` on a binding — `BindingInterface` has only
19
+ `name`/`referenceId`, verified in backend `types/forces/binding_interface.rb`).
20
+ - **Specs added** (render + semantic, offline, no creds): `page_with_forces_spec.rb`,
21
+ `pages_workflow_commands_spec.rb` (11 examples; verified they fail against the pre-fix code).
22
+ Each validates the rendered doc against a minimal SDL carrying the real union shape.
23
+ - **Not yet run in CI:** the job is inert until the four `EP_CI_*` CI/CD variables are set
24
+ (service account with read access on a NON-production org introspection needs no write
25
+ scope). `dump_schema.rb` has therefore never talked to a live endpoint. Its first real run is
26
+ the acceptance test for this item.
27
+
28
+ - [ ] **Force binding read/write asymmetry (found 2026-07-29 while fixing `ForceFields`)**
29
+ `WorkflowEditBindingInput` and `removeBinding` require a binding `id`, but the read side
30
+ (`Types::Forces::BindingInterface`) exposes only `name` / `referenceId` / `reference`. So
31
+ `Base::Force::Binding#id` (`passkey :id`) can never be populated, and
32
+ `Force::BindingCollection#delete!(binding_object)` sends `removeBinding: { id: nil }`.
33
+ Not fixable client-side needs `id` on the binding types (backend), or the write commands need
34
+ to key on `referenceId` + `name`. Belongs with the shape-asymmetry review project. No regression
35
+ from the fragment fix: the query that would have fed it never succeeded.
36
+ Priority: medium — silently broken write path.
37
+
38
+ - [x] **Builder::Register** — `createRegister`, `updateRegister`, `destroyRegister` mutations.
39
+ `Base::Register`, `Model::Register`, `Input::Register::Create/Update`, `Payload::Register`.
40
+ `Builder::Register` with `create`, `update`, `destroy`, and `preset_view` sub-builder.
41
+ `GraphQL#register` exposed (singular, distinct from `#registers` compat layer).
42
+ *Done 2026-06-08*
43
+
44
+ - [ ] **Dashboards / Charts** — `Register.defaultDashboardId` and dashboard queries/mutations
45
+ are not yet wrapped. Backend has dashboard configuration tied to registers and organisations.
46
+ Scope: `Base::Dashboard` model, `Query::Dashboard(s)`, `Builder::Register#set_default_dashboard`.
47
+ Priority: medium needed when scripts need to manage register dashboard configs.
48
+
49
+ - [x] **AI field mutations** `generateAiSummary`, `generateSmartFill`,
50
+ `submitAiSummaryFeedback`, `submitSmartFillFeedback` fully wrapped.
51
+ `Mutation::AiSummary::Generate/SubmitFeedback`, `Mutation::SmartFill::Generate/SubmitFeedback`,
52
+ `Payload::AiSummaryGenerate`, `Payload::OkPayload`, `Base::AiSummaryVersion`.
53
+ `Builder::Page` wired: `generate_ai_summary`, `submit_ai_summary_feedback`,
54
+ `generate_smart_fill`, `submit_smart_fill_feedback`.
55
+ *Done 2026-06-08*
56
+
57
+ - [ ] **AI prompt review workflow** — AiSummary and SmartFill fields store an `instructions`
58
+ field (the AI prompt, template-configured by humans). No audit/review workflow exists.
59
+ The gem can read `field.instructions` on AiSummary/SmartFill instances already.
60
+ What's needed: a way to scan pages/templates for these instructions and surface them
61
+ for review. Possibly: `Query::PagesWithAiFields` + a review report script.
62
+ See `.ai-assistance/code/ecoPortal_architecture/13_ai_infrastructure.md` for context.
63
+ Priority: low/design — the need is real but the right interface is TBD.
64
+
65
+ - [x] **eP Meta AI scaffolding project** — Standalone template repo at
66
+ `C:\ruby_scripts\git\ecoPortal_ai_standards`. Bridge protocol, all scripts
67
+ (lock-acquire, task-read, task-create, setup-mcps, etc.), all skills, conventions,
68
+ integrations, capabilities registry, CLAUDE.md template ({{PLACEHOLDER}} vars),
69
+ ONBOARDING.md (15-min setup guide), `init-project.ts` bootstrap script.
70
+ Push to GitLab to share: `git@gitlab.ecoportal.co.nz:oscar/ecoPortal_ai_standards.git`
71
+ *Done 2026-06-08*
72
+
73
+ - [ ] **Commit unstaged changes** Large set of modified files on `ai_dev_process` branch
74
+ not yet staged or committed. Review and commit once session is fully restored.
75
+
76
+ ## Bridge improvements (from Gemini review 2026-06-04)
77
+
78
+ - [x] **Security: Code must prompt before executing bridge-requested shell commands**
79
+ Rule added to `.ai-assistance/bridge/CLAUDE.md` "Running Code non-interactively" section.
80
+ Code must surface any shell command to the user before running it, even in
81
+ skip-permissions mode. User denial mark task FAILED.
82
+ *Done 2026-06-08*
83
+
84
+ - [x] **Atomic LOCK acquisition** — `scripts/lock-acquire.sh` implemented.
85
+ Uses temp-file + hard-link (atomic on POSIX/NTFS); falls back to bash `noclobber`.
86
+ Reports held-by agent/intent on contention. Auto-detects stale locks by mtime.
87
+ `bridge/CLAUDE.md` updated to reference it as the preferred acquisition method.
88
+ *Done 2026-06-08*
89
+
90
+ - [x] **Stale IN_PROGRESS recovery** — `bridge-init.sh` updated: scans for IN_PROGRESS
91
+ tasks older than 1 hour (via `stat` mtime), reports them in `stale_tasks` + `stale`
92
+ count in STATUS JSON. `bridge/CLAUDE.md` updated with Code's required response:
93
+ report to user, ask to reset to PENDING or mark FAILED.
94
+ *Done 2026-06-08*
95
+
96
+ - [x] **`task-read.ts` script** — `scripts/task-read.ts` implemented.
97
+ Parses all sections (title, status, created, from, to, context, request, expected,
98
+ result, notes) from inbox/outbox/archive files. Searches all bridge dirs automatically.
99
+ Output: structured JSON. Saves ~200 tokens per task read vs raw Markdown.
100
+ *Done 2026-06-08*
101
+
102
+ - [x] **Archive pruning convention** — Documented in `bridge/CLAUDE.md` "Archive pruning"
103
+ section: keep last 90 days or last 50 task pairs; git history is the audit trail;
104
+ prune manually when folder gets unwieldy.
105
+ *Done 2026-06-08*
106
+
107
+ ## File upload
108
+
109
+ - [x] **BUG — `FileUpload::Client` auth mechanism (confirmed live 2026-07-26, fixed same day).**
110
+ Implemented in commit `9f769cc` (2026-06-08) as a port of `ecoportal-api-v2`'s
111
+ `S3::Data`/`S3::Upload`/`S3::Files` — shipped in CHANGELOG but with **zero test coverage
112
+ ever** (no specs, no VCR, no manual test script). Live-verified via `training` repo →
113
+ `mini/automated-tests/tests/pages/file_upload_test.rb`: `Query::FileUploadSignature`
114
+ (step 1, GraphQL presign) succeeds, but the REST registration step
115
+ (`POST /api/v2/<org_id>/s3/files`, step 3) **404s**.
116
+ **Root cause:** `ecoportal-api-v2`'s REST S3 endpoints authenticate via
117
+ `X-ECOPORTAL-API-KEY` header (`Common::Content::Client#base_request`), but the ported
118
+ `FileUpload::Client` sends `Authorization: Bearer <oauth_token>` instead (the same token
119
+ used for GraphQL) — wrong auth mechanism for those specific REST endpoints.
120
+ **Fix (branch `fix/file-upload-api-key-auth`):** added `api_key:` to
121
+ `Ecoportal::API::GraphQL.new` (threaded to `HttpClient`, independent of the GraphQL
122
+ endpoint's own email/pass OAuth bearer token), exposed `HttpClient#api_key` publicly, and
123
+ changed `FileUpload::Client#upload_get`/`#upload_post` to send `X-ECOPORTAL-API-KEY`
124
+ instead of `Authorization: Bearer`, raising a clear error if no `api_key:` was configured.
125
+ 18 new specs added (`graphql_spec.rb`, `http_client_spec.rb`, `file_upload_signature_spec.rb`,
126
+ `file_upload/client_spec.rb` — full 4-step `#upload` orchestration + auth-header assertions).
127
+ **Still NOT live-verified** — no credentials were available in the environment this was
128
+ fixed in; run `training/mini/automated-tests -only pages/file_upload` (with a real
129
+ `api_key:` wired into that harness's `graphql` session helper — check where it builds
130
+ `Ecoportal::API::GraphQL.new` and add `api_key:` there too) before trusting this in
131
+ production.
132
+ **Still open / NOT covered by this fix:**
133
+ - The S3 key path is built by string concatenation (`upload_prefix + filename`) vs v2's
134
+ slash-joined `"#{user_tmpdir}/#{file_basename}"`.
135
+ - The multipart POST hardcodes `x-amz-server-side-encryption: AES256` instead of reading
136
+ the value v2 gets from the presigned credentials response.
137
+ - The hand-rolled multipart builder should probably be replaced with `Net::HTTP#set_form`
138
+ (what v2 uses, more robust than hand-built boundaries).
139
+ - No mutation exists anywhere in this gem to set `FileContainer#tags` — confirm whether
140
+ that's even possible via GraphQL before promising it in any customer-facing demo.
141
+ - **Threading/multi-file:** `ecoportal-api-v2` has a real, previously-uncovered threaded
142
+ batch-upload path (`S3::Files::BatchUpload` + `Concerns::Threadable`, `threads:` param,
143
+ per-file error isolation) — now specced (`ecoportal-api-v2` branch, 3 new specs).
144
+ Assessment: do NOT port this to `FileUpload::Client` yet — it only handles one file per
145
+ call today, and Oscar has already explicitly deferred a bulk/multi-file DX shortcut here
146
+ in favor of a future backend async batch-upload feature (out of scope for this gem).
147
+ Revisit only once the auth fix is live-verified as a working single-file baseline AND
148
+ bulk latency is confirmed to actually matter in practice.
149
+ Priority: was **High** (blocked `ep-api-collections`' Files Upload group and any real
150
+ usage of `#file_upload`) — auth mechanism now fixed pending live verification; the Files
151
+ Upload collection group should stay un-built until that live verification passes.
152
+
153
+ - [ ] **File upload — data field wiring (original scope, still valid once the bug above is fixed)**
154
+ Support uploading files to attach to `File` and `ImageGallery` data fields (and
155
+ potentially Action file attachments at a later stage). Distinct from `attach` (which
156
+ links existing resources). Scope:
157
+ - Create `Input::FileAttachment` to carry the resulting file container ID into mutations
158
+ - Wire into data field update inputs (Phase E concern for fields, sooner for Actions)
159
+ Priority: Medium — needed before data field updates can be fully functional.
160
+ Note: Actions file attachment may be needed sooner — track separately if it becomes urgent.
161
+
162
+ ## Completed
163
+
164
+ - [x] **Gemini design review of bridge architecture** — Done 2026-06-04. Response in
165
+ `.ai-assistance/bridge/context/gemini-review-response.md`.
166
+ - [x] **Regenerate GitLab PAT** — New token generated, April 2027 expiry, rotation enabled.
167
+ Updated in `.env` and documented in `integrations/gitlab-mcp.md`.
168
+ - [x] **Rename `.claude/` to `.ai-assistance/`** — Done 2026-06-04. All references updated
169
+ across scripts, CLAUDE.md, gitignore, and capabilities docs.
170
+ - [x] **MCP setup script** — `setup-mcps.ts` + tests written. Teammates run once per machine.
@@ -1,48 +1,48 @@
1
- # SKILL: AI Instructions Generator, Reviewer & Updater
2
-
3
- **Purpose:** Keep CLAUDE.md, skill files, and conventions accurate, tidy, and placed correctly as the project evolves.
4
-
5
- ---
6
-
7
- ## When to Use
8
-
9
- - A developer makes an observation that reveals a gap, mistake, or new convention.
10
- - A new pattern emerges in the code that future AI agents should know about.
11
- - A skill needs to be created, updated, or split.
12
- - CLAUDE.md needs to reflect a structural change to the repo.
13
-
14
- ---
15
-
16
- ## Decision: Practice/Convention vs. CLAUDE.md Instruction vs. Skill
17
-
18
- When an observation is made, scope it:
19
-
20
- | Type | Where it goes |
21
- |------|--------------|
22
- | One-off note or context | Inline comment in the relevant `.ai-assistance/code/*.md` doc |
23
- | Convention (how we do things here) | `CLAUDE.md` → Conventions section |
24
- | Always-do behaviour for AI agents | `CLAUDE.md` → Before Starting Any Task, or a new section |
25
- | Reusable, invocable capability | New or updated `SKILL.md` in `.ai-assistance/skills/<skill-name>/` |
26
-
27
- ---
28
-
29
- ## File Placement Rules
30
-
31
- - **CLAUDE.md** lives at repo root — one file, always.
32
- - **Skills** live at `.ai-assistance/skills/<skill-name>/SKILL.md`.
33
- - Additional assets (scripts, prompts) live alongside the SKILL.md in the same folder.
34
- - **Code specs** live at `.ai-assistance/code/` (see `code-specs` skill).
35
- - **Project files** live at `.ai-assistance/projects/<project-name>/` (see `project-cycle` skill).
36
- - **Refactoring logs** live at `.ai-assistance/code/refactoring/` (see `refactor` skill).
37
-
38
- **Never scatter instruction files in code directories.** All AI tooling lives under `.ai-assistance/`.
39
-
40
- ---
41
-
42
- ## Workflow
43
-
44
- 1. Identify the type of observation (see table above).
45
- 2. Locate the correct file. Create it if it doesn't exist.
46
- 3. Make the minimal change — don't rewrite documents unnecessarily.
47
- 4. Update the skill index table in CLAUDE.md if a new skill was added.
48
- 5. Confirm with the developer if the change affects an existing convention that other developers rely on.
1
+ # SKILL: AI Instructions Generator, Reviewer & Updater
2
+
3
+ **Purpose:** Keep CLAUDE.md, skill files, and conventions accurate, tidy, and placed correctly as the project evolves.
4
+
5
+ ---
6
+
7
+ ## When to Use
8
+
9
+ - A developer makes an observation that reveals a gap, mistake, or new convention.
10
+ - A new pattern emerges in the code that future AI agents should know about.
11
+ - A skill needs to be created, updated, or split.
12
+ - CLAUDE.md needs to reflect a structural change to the repo.
13
+
14
+ ---
15
+
16
+ ## Decision: Practice/Convention vs. CLAUDE.md Instruction vs. Skill
17
+
18
+ When an observation is made, scope it:
19
+
20
+ | Type | Where it goes |
21
+ |------|--------------|
22
+ | One-off note or context | Inline comment in the relevant `.ai-assistance/code/*.md` doc |
23
+ | Convention (how we do things here) | `CLAUDE.md` → Conventions section |
24
+ | Always-do behaviour for AI agents | `CLAUDE.md` → Before Starting Any Task, or a new section |
25
+ | Reusable, invocable capability | New or updated `SKILL.md` in `.ai-assistance/skills/<skill-name>/` |
26
+
27
+ ---
28
+
29
+ ## File Placement Rules
30
+
31
+ - **CLAUDE.md** lives at repo root — one file, always.
32
+ - **Skills** live at `.ai-assistance/skills/<skill-name>/SKILL.md`.
33
+ - Additional assets (scripts, prompts) live alongside the SKILL.md in the same folder.
34
+ - **Code specs** live at `.ai-assistance/code/` (see `code-specs` skill).
35
+ - **Project files** live at `.ai-assistance/projects/<project-name>/` (see `project-cycle` skill).
36
+ - **Refactoring logs** live at `.ai-assistance/code/refactoring/` (see `refactor` skill).
37
+
38
+ **Never scatter instruction files in code directories.** All AI tooling lives under `.ai-assistance/`.
39
+
40
+ ---
41
+
42
+ ## Workflow
43
+
44
+ 1. Identify the type of observation (see table above).
45
+ 2. Locate the correct file. Create it if it doesn't exist.
46
+ 3. Make the minimal change — don't rewrite documents unnecessarily.
47
+ 4. Update the skill index table in CLAUDE.md if a new skill was added.
48
+ 5. Confirm with the developer if the change affects an existing convention that other developers rely on.
@@ -1,69 +1,69 @@
1
- # SKILL: Code Specs for AI
2
-
3
- **Purpose:** Maintain AI-readable markdown documentation in `.ai-assistance/code/` so that future AI agents don't need to re-analyse code from scratch. These docs are shortcuts, not replacements — when real analysis is needed, always update them.
4
-
5
- ---
6
-
7
- ## When to Use
8
-
9
- - After analysing a new area of the codebase.
10
- - Before starting work in an area — check if a doc exists and whether it's stale.
11
- - After making changes that alter the understanding of an area.
12
- - Periodically (especially at project cycle-end) — use Gemini Assist to spot stale sections.
13
-
14
- ---
15
-
16
- ## Document Structure
17
-
18
- Each code spec document (`.ai-assistance/code/<area>.md`) must include:
19
-
20
- ```markdown
21
- # Code Spec: <Area Name>
22
-
23
- **Scope:** What this document covers. What it explicitly does NOT cover.
24
- **Last updated:** YYYY-MM-DD
25
- **Key files:** List of the most important files in this area.
26
-
27
- ---
28
-
29
- ## Overview
30
- Brief description of what this area does and its role in the gem.
31
-
32
- ## Key Classes / Modules
33
- For each significant class: one-line purpose, key public methods/interface.
34
-
35
- ## Patterns & Conventions
36
- Design patterns, inheritance chains, naming conventions specific to this area.
37
-
38
- ## Dependencies
39
- What this area depends on (internal and external). What depends on it.
40
-
41
- ## Gotchas / Non-Obvious Behaviours
42
- Things that would cause confusion or bugs if not known upfront.
43
-
44
- ## TODOs / Open Questions
45
- Pending items specific to this area. Link to project TODO if applicable.
46
- ```
47
-
48
- ---
49
-
50
- ## Naming & Placement
51
-
52
- Mirror the `lib/` structure:
53
-
54
- | Code area | Doc path |
55
- |-----------|---------|
56
- | `lib/ecoportal/api/graphql/model/` | `.ai-assistance/code/model.md` |
57
- | `lib/ecoportal/api/graphql/input/` | `.ai-assistance/code/input.md` |
58
- | `lib/ecoportal/api/graphql/logic/` | `.ai-assistance/code/logic.md` |
59
- | Whole gem overview | `.ai-assistance/code/OVERVIEW.md` |
60
-
61
- For deeply nested areas, use subdirectories: `.ai-assistance/code/model/location_structure.md`
62
-
63
- ---
64
-
65
- ## Keeping Docs Fresh
66
-
67
- - When you read a file and find something the doc doesn't mention — add it.
68
- - When a refactor changes a class — update the corresponding doc.
69
- - Use the `gemini-assist` skill for batch reviews of multiple docs vs. current code.
1
+ # SKILL: Code Specs for AI
2
+
3
+ **Purpose:** Maintain AI-readable markdown documentation in `.ai-assistance/code/` so that future AI agents don't need to re-analyse code from scratch. These docs are shortcuts, not replacements — when real analysis is needed, always update them.
4
+
5
+ ---
6
+
7
+ ## When to Use
8
+
9
+ - After analysing a new area of the codebase.
10
+ - Before starting work in an area — check if a doc exists and whether it's stale.
11
+ - After making changes that alter the understanding of an area.
12
+ - Periodically (especially at project cycle-end) — use Gemini Assist to spot stale sections.
13
+
14
+ ---
15
+
16
+ ## Document Structure
17
+
18
+ Each code spec document (`.ai-assistance/code/<area>.md`) must include:
19
+
20
+ ```markdown
21
+ # Code Spec: <Area Name>
22
+
23
+ **Scope:** What this document covers. What it explicitly does NOT cover.
24
+ **Last updated:** YYYY-MM-DD
25
+ **Key files:** List of the most important files in this area.
26
+
27
+ ---
28
+
29
+ ## Overview
30
+ Brief description of what this area does and its role in the gem.
31
+
32
+ ## Key Classes / Modules
33
+ For each significant class: one-line purpose, key public methods/interface.
34
+
35
+ ## Patterns & Conventions
36
+ Design patterns, inheritance chains, naming conventions specific to this area.
37
+
38
+ ## Dependencies
39
+ What this area depends on (internal and external). What depends on it.
40
+
41
+ ## Gotchas / Non-Obvious Behaviours
42
+ Things that would cause confusion or bugs if not known upfront.
43
+
44
+ ## TODOs / Open Questions
45
+ Pending items specific to this area. Link to project TODO if applicable.
46
+ ```
47
+
48
+ ---
49
+
50
+ ## Naming & Placement
51
+
52
+ Mirror the `lib/` structure:
53
+
54
+ | Code area | Doc path |
55
+ |-----------|---------|
56
+ | `lib/ecoportal/api/graphql/model/` | `.ai-assistance/code/model.md` |
57
+ | `lib/ecoportal/api/graphql/input/` | `.ai-assistance/code/input.md` |
58
+ | `lib/ecoportal/api/graphql/logic/` | `.ai-assistance/code/logic.md` |
59
+ | Whole gem overview | `.ai-assistance/code/OVERVIEW.md` |
60
+
61
+ For deeply nested areas, use subdirectories: `.ai-assistance/code/model/location_structure.md`
62
+
63
+ ---
64
+
65
+ ## Keeping Docs Fresh
66
+
67
+ - When you read a file and find something the doc doesn't mention — add it.
68
+ - When a refactor changes a class — update the corresponding doc.
69
+ - Use the `gemini-assist` skill for batch reviews of multiple docs vs. current code.