aravind changes
This commit is contained in:
@@ -1840,7 +1840,7 @@ Recorded in `docs/api-contract.md` §12 and still accurate against the current c
|
||||
| **GCS-compatible object storage** | — | **Future direction.** No reference in the repository; `infrastructure/README.md` names MinIO as a "later" candidate | — |
|
||||
| **Docker deployment** | — | **Future direction.** `infrastructure/` contains only a README; `Dockerfile.api` and `Dockerfile.owliver` are listed there as later work | — |
|
||||
| **Redis** | Shared state for rate limiting across instances | **Future direction.** `ratelimit.go` names Redis or the database as the seam; nothing is wired | Needed before multi-instance deployment for the limiter to mean anything |
|
||||
| **NATS is not part of the target architecture** | — | **Future direction / stated rule.** Note the discrepancy: `infrastructure/README.md` currently lists NATS as a later docker-compose candidate. See §17. | Remove NATS from that table if the rule stands |
|
||||
| **NATS is not part of the target architecture** | — | **Future direction / stated rule.** `infrastructure/README.md` previously listed NATS as a later docker-compose candidate; that table has been corrected. See §17.17. | Keep it out |
|
||||
| **RAG / pgvector** | — | **Future direction.** `pgvector` is not installed in the local database and is named only once, in `infrastructure/README.md` | Introduce when the architecture calls for it |
|
||||
|
||||
---
|
||||
@@ -1850,35 +1850,31 @@ Recorded in `docs/api-contract.md` §12 and still accurate against the current c
|
||||
Everything below was checked against the current repository. Items the request asked
|
||||
about that could not be verified are marked as such rather than guessed at.
|
||||
|
||||
### 17.1 Documentation is behind the code
|
||||
### 17.1 Documentation is behind the code — resolved
|
||||
|
||||
**Issue.** `README.md` describes the repository as being at an earlier stage than the
|
||||
code is. It states "Authorization — which roles may do what — is Phase 3D and is not
|
||||
implemented", "Authorization is **not** implemented. `users.role` is carried on the
|
||||
identity and consulted nowhere: any signed-in user reaches every endpoint", "38
|
||||
endpoints" and "55 tests".
|
||||
**Issue as recorded.** `README.md` described the repository as being at an earlier
|
||||
stage than the code is. It stated "Authorization — which roles may do what — is Phase
|
||||
3D and is not implemented", "Authorization is **not** implemented. `users.role` is
|
||||
carried on the identity and consulted nowhere: any signed-in user reaches every
|
||||
endpoint", "38 endpoints" and "55 tests". The same staleness appeared in two source
|
||||
comments: the `internal/httpserver/server.go` package documentation ("Authorization is
|
||||
NOT here"), and `internal/authctx/authctx.go` ("It is NOT consulted anywhere in Phase
|
||||
3C: authentication only").
|
||||
|
||||
**Cause.** Authorization, the definition tables, the CRUD surface and the runtime all
|
||||
landed after the README was last revised.
|
||||
|
||||
**Impact.** A reader trusting the README would conclude that any signed-in user
|
||||
reaches every endpoint, which is not what the code does.
|
||||
|
||||
**Current behaviour.** `internal/domain/policy.go`, `Server.authorize`,
|
||||
`builder.ownership` and `internal/httpserver/rbac_test.go` (730 lines) all exist and
|
||||
run. 51 routes are registered. 175 test functions run.
|
||||
`docs/api-contract.md` §9A *is* current and documents the authorization contract
|
||||
accurately.
|
||||
run. 51 routes are registered. 175 test functions run. `docs/api-contract.md` §9A
|
||||
*is* current and documents the authorization contract accurately.
|
||||
|
||||
**Possible future handling.** Revise `README.md` against the code.
|
||||
|
||||
The same staleness appears in two source comments:
|
||||
|
||||
- `internal/httpserver/server.go` package documentation: "Authorization is NOT here.
|
||||
A signed-in user reaches every endpoint they could reach before".
|
||||
- `internal/authctx/authctx.go`: "It is NOT consulted anywhere in Phase 3C:
|
||||
authentication only" — `Identity.Role` is now consulted by `Server.authorize`,
|
||||
`builder.ownership`, `guardInsert` and `service/definitions.go`.
|
||||
**Resolution.** `README.md` was revised against the code: the status paragraph, the
|
||||
layout tree (which was missing `cmd/setpassword`, `internal/auth`, `internal/authctx`,
|
||||
`internal/definition` and `internal/runtime`), the route count, the test count and the
|
||||
authorization section. The `server.go` and `authctx.go` package comments were
|
||||
corrected to describe the authorization that exists. `internal/orgctx/orgctx.go`,
|
||||
which still framed itself as pre-authentication, was corrected in the same pass.
|
||||
|
||||
### 17.2 The definitions endpoints are not in the API contract
|
||||
|
||||
@@ -2000,23 +1996,26 @@ the effective limit multiplies by instance count, resets on restart, and degrade
|
||||
a global budget behind a reverse proxy. **Possible future handling:** move the
|
||||
limiter behind shared state before deploying more than one instance.
|
||||
|
||||
### 17.10 The repository has no commits
|
||||
### 17.10 The repository has almost no history
|
||||
|
||||
**Issue.** `git log` reports `fatal: your current branch 'main' does not have any
|
||||
commits yet`. Every file is untracked.
|
||||
**Issue as recorded.** `git log` reported `fatal: your current branch 'main' does not
|
||||
have any commits yet`, and every file was untracked.
|
||||
|
||||
**Impact.** There is no history, no recovery point, no blame, and no record of when
|
||||
any of the work described in §2 happened. The chronology in this document was
|
||||
reconstructed from migration headers, package documentation and the contract, not
|
||||
from version control.
|
||||
**Current behaviour.** The tree is now committed: a single commit on `main`
|
||||
(`7d12ebe`, "first commit") holds the whole repository.
|
||||
|
||||
**Note.** This document does not change that; no commit was made.
|
||||
**Remaining impact.** One commit is not history. There is still no blame, no
|
||||
incremental recovery point, and no record of when any of the work described in §2
|
||||
happened. The chronology in this document was reconstructed from migration headers,
|
||||
package documentation and the contract, not from version control, and that remains
|
||||
the only source for it.
|
||||
|
||||
### 17.11 A minor documentation defect in the source
|
||||
### 17.11 A minor documentation defect in the source — resolved
|
||||
|
||||
`internal/httpserver/api.go` — the doc comment describing `decodeBody` sits
|
||||
immediately above `decodeInto`, so `decodeInto` carries two doc comments and
|
||||
`decodeBody` carries none.
|
||||
`internal/httpserver/api.go` — the doc comment describing `decodeBody` sat
|
||||
immediately above `decodeInto`, so `decodeInto` carried two doc comments and
|
||||
`decodeBody` carried none. The `decodeBody` comment has been moved to sit above
|
||||
`decodeBody`.
|
||||
|
||||
### 17.12 Badge endpoint mismatch — verified
|
||||
|
||||
@@ -2091,8 +2090,9 @@ among the things that do not exist yet.
|
||||
|
||||
**Impact.** A reader of `infrastructure/README.md` would take NATS to be planned.
|
||||
|
||||
**Possible future handling.** Amend that table if the rule stands. Nothing was changed
|
||||
here.
|
||||
**Resolution.** The rule stands, so the table was amended: `infrastructure/README.md`
|
||||
no longer lists NATS as a candidate and says explicitly that it is not part of the
|
||||
target architecture. `README.md` no longer names it either.
|
||||
|
||||
### 17.18 Deliberate contract behaviours that read as defects
|
||||
|
||||
@@ -2169,8 +2169,8 @@ deliberately and should be done knowingly.
|
||||
|
||||
### NATS
|
||||
|
||||
**NATS is not part of the target architecture.** Note that `infrastructure/README.md`
|
||||
currently lists it as a later candidate; see §17.17.
|
||||
**NATS is not part of the target architecture.** `infrastructure/README.md` no longer
|
||||
lists it as a candidate; see §17.17.
|
||||
|
||||
### Nearest-term work implied by the code itself
|
||||
|
||||
@@ -2281,9 +2281,9 @@ disposable `krow_backend_autotest_<pid>` database per test process.
|
||||
**Current Known Limitations:** no AI execution and no public runtime endpoint; login
|
||||
rate limiting is per-process and in-memory; CORS does not permit credentials;
|
||||
definitions endpoints bypass the policy table; the runtime package is unreachable
|
||||
from the running service; `README.md` and two source comments are behind the code;
|
||||
the definitions endpoints are absent from the API contract; attendance data is empty
|
||||
without a rostering source; the repository has no commits.
|
||||
from the running service; the definitions endpoints are absent from the API contract;
|
||||
attendance data is empty without a rostering source; the repository has a single
|
||||
commit and so no usable history.
|
||||
|
||||
**Current Development Focus:** the most recent work in the tree is the definition
|
||||
system — schema, parser conformance, CRUD — and the runtime boundary that sits on top
|
||||
@@ -2392,13 +2392,12 @@ is how this codebase would stop being trustworthy.
|
||||
- **The main current limitations** are: no AI execution and no runtime endpoint;
|
||||
login rate limiting that does not survive scale-out; CORS that does not yet permit
|
||||
credentials; ten definition endpoints that sit outside the policy table and outside
|
||||
the written contract; documentation that is behind the code; and a repository with
|
||||
no commits.
|
||||
the written contract; and a repository with a single commit and so no usable
|
||||
history.
|
||||
- **The direction** is real execution behind the existing executor interfaces
|
||||
(Owliver / an LLM provider abstraction), then retrieval, then tooling, then
|
||||
deployment infrastructure — none of which exists here today. **NATS is not part of
|
||||
the target architecture**, and the one place in the repository that still names it
|
||||
should be corrected.
|
||||
the target architecture**, and the documentation no longer implies otherwise.
|
||||
- **The rules that must not be broken** are in §21. The two that matter most in daily
|
||||
work: never trust a client-supplied identity or tenant, and never rewrite stored
|
||||
Markdown.
|
||||
@@ -2409,3 +2408,9 @@ is how this codebase would stop being trustworthy.
|
||||
behaviour above was read from the current checkout or from read-only queries against
|
||||
the local development database. Nothing in the repository was modified to produce
|
||||
this document.*
|
||||
|
||||
*Revised on 2026-08-24 by a structure-and-dead-code cleanup pass, which changed no
|
||||
schema, no migration, no database row and no runtime behaviour. What it did change is
|
||||
recorded in §17.1, §17.10, §17.11 and §17.17: documentation and source comments that
|
||||
had fallen behind the code were corrected. The counts above were re-verified against
|
||||
the checkout and are unchanged.*
|
||||
|
||||
@@ -129,6 +129,125 @@ these would leave the shim with methods that 404. See §11 (D6).
|
||||
|
||||
---
|
||||
|
||||
## 2A. Owliver suggestions
|
||||
|
||||
`GET /api/v1/owliver/suggestions?page={surface}&query={typed}`
|
||||
|
||||
The one endpoint here that serves no resource. It answers "what could I usefully
|
||||
ask on this page?" for the Owliver panel, which calls it while the user types —
|
||||
so it reads no table, opens no transaction, calls no model, and its whole answer
|
||||
is computed from a static catalogue in `internal/owliver`.
|
||||
|
||||
It is not on the public allowlist. Which readings exist depends on the caller's
|
||||
role, so there is no anonymous answer to give.
|
||||
|
||||
### Request
|
||||
|
||||
| Parameter | Required | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `page` | yes | A surface id from the closed page vocabulary — the same one `internal/definition` validates a definition's `pages:` against. Aliases (`hired`, `forge`, `new-position`) and loose spellings (`Talent Pool`) resolve to the canonical id. |
|
||||
| `query` | no | What the user has typed so far. |
|
||||
|
||||
Any other parameter is `invalid_query`. **Nothing about the caller is accepted
|
||||
here** — role, organization and user are read from the session, and a request
|
||||
that names one is refused rather than ignored.
|
||||
|
||||
An unknown `page` is `invalid_query`, with the frontend's own wording:
|
||||
`Unsupported page: {value}. Supported pages: {…}.` An absent, blank or
|
||||
too-short `query` is **not** an error — there is simply nothing to rank yet.
|
||||
|
||||
### Response
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"suggestions": [
|
||||
{ "text": "Which position has the strongest pipeline?", "intent": "position-strength" },
|
||||
{ "text": "Show hiring activity as a flow", "intent": "hiring-operations", "capability": "flow" }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`data.suggestions` is always an array — `[]` when nothing matches, never `null`
|
||||
and never an error. There is no `meta`: the list is capped rather than paged.
|
||||
|
||||
| Field | Meaning |
|
||||
| --- | --- |
|
||||
| `text` | The question, as the user reads it. |
|
||||
| `intent` | The **frontend capability id** the panel dispatches on, verbatim from the manifests in `src/components/ai-assistant/capabilities/`. Not a backend identifier, and never invented here. |
|
||||
| `capability` | The section type to draw the answer as, from the closed `OWLIVER_CAPABILITIES` vocabulary. Present only when the query asked for one ("as a flow", "summarize"); absent otherwise. |
|
||||
|
||||
Nothing internal is exposed: no matching terms, no resource names, no scores, no
|
||||
policy detail. `text` is always catalogue wording — no part of the query is
|
||||
echoed back into a suggestion.
|
||||
|
||||
### Selection
|
||||
|
||||
Five stages, each of which only ever removes:
|
||||
|
||||
```
|
||||
the page's catalogue → permission → relevance → deduplicate → top 3
|
||||
```
|
||||
|
||||
- **Page.** Intents are keyed by surface, so a suggestion from another page
|
||||
cannot appear. The same word answers differently per page by construction:
|
||||
`pipeline` on `positions` is about which role converts, on `candidates` it is
|
||||
the funnel the applicants are in.
|
||||
- **Permission.** Each intent declares the resources it reads, and those are
|
||||
checked against the policy table in §9A — *before* ranking, so a refused
|
||||
reading is never scored. Two gates, not one: the role must be allowed the
|
||||
operation, and for an organization-wide reading the role's rows must not be
|
||||
narrowed. Talent may list job applications; talent may not be offered "which
|
||||
position has the strongest pipeline?", because their view of that resource is
|
||||
their own rows. No role list is written down here — see §9A.1.
|
||||
- **Relevance.** Deterministic keyword ranking over the intent's own terms.
|
||||
Exact token, then multi-word phrase, then prefix (so a half-typed word still
|
||||
matches), then extension. Ties break on catalogue order, so the same request
|
||||
always answers identically. A query naming only a section type ranks the
|
||||
page's readings; once it names a subject, readings that merely *support* that
|
||||
shape are dropped rather than used as padding.
|
||||
- **Deduplicate.** One suggestion per intent id, and no two with the same text.
|
||||
- **Cap.** Three. Nothing is added to reach three.
|
||||
|
||||
A query with fewer than two letters or digits after normalization returns `[]`.
|
||||
|
||||
### Normalization
|
||||
|
||||
The query is truncated to 200 characters, lower-cased, and reduced to letters,
|
||||
digits and single spaces — every other character becomes a space rather than
|
||||
being stripped, so nothing can be glued into a token that was not typed as one.
|
||||
|
||||
There is no injection surface to defend: the normalized text is compared against
|
||||
a fixed table of literals and never reaches SQL, a template, a shell or a log
|
||||
message. Hostile input is ranked like any other text, and can only ever produce
|
||||
entries the catalogue already holds.
|
||||
|
||||
### Where the catalogue comes from
|
||||
|
||||
The frontend owns the vocabulary. Owliver's capabilities are declared per page
|
||||
context in `src/components/ai-assistant/capabilities/`; `internal/owliver`
|
||||
transcribes the id and the page, and adds the two things a manifest does not
|
||||
carry — the words that mean a user is reaching for that reading, and the records
|
||||
it reads. Same pattern as `internal/definition/vocabulary.go`, and for the same
|
||||
reason: one vocabulary, named from both ends, with a test on this side that
|
||||
fails when an id here names no capability there.
|
||||
|
||||
**No table, no migration.** The suggestions are derived from definitions that
|
||||
already exist. Persistence would only be warranted if suggestions became
|
||||
admin-managed, and nothing in the product asks for that today.
|
||||
|
||||
### Not covered
|
||||
|
||||
The seven workspace and configuration surfaces — `settings`, `workspace`,
|
||||
`workspace-agents`, `workspace-skills`, `workspace-skill-configure`,
|
||||
`skill-development`, `workspace-agent-configure` — are valid pages with no
|
||||
entries. Their panel answers from the registries rather than from workforce
|
||||
records, so there is nothing to rank a typed query against. They return `[]`,
|
||||
which is the honest answer, not a validation error.
|
||||
|
||||
---
|
||||
|
||||
## 3. Request schemas
|
||||
|
||||
### 3.1 Create — `POST /{resource}`
|
||||
|
||||
1566
docs/backend-implementation-plan.md
Normal file
1566
docs/backend-implementation-plan.md
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user