aravind changes

This commit is contained in:
2026-08-25 16:37:05 +05:30
parent cadea4bd92
commit b6f8655909
27 changed files with 5058 additions and 163 deletions

View File

@@ -150,7 +150,7 @@ func (s *Service) Get(ctx context.Context, ident authctx.Identity, id string) (d
// Create validates and inserts, returning the complete stored record.
func (s *Service) Create(ctx context.Context, ident authctx.Identity, body domain.Record) (domain.Record, error) {
clean, err := s.validate(body, true)
clean, err := s.validate(ident, body, true)
if err != nil {
return nil, err
}
@@ -162,7 +162,7 @@ func (s *Service) Update(ctx context.Context, ident authctx.Identity, id string,
if !isUUID(id) {
return nil, domain.NotFound(s.res.Name, id)
}
clean, err := s.validate(patch, false)
clean, err := s.validate(ident, patch, false)
if err != nil {
return nil, err
}
@@ -201,7 +201,11 @@ func (s *Service) Delete(ctx context.Context, ident authctx.Identity, id string)
// exactly how `interview_id`, `training_outline` and `score_breakdown` would
// have been lost: the frontend would have written them, the API would have
// accepted the request, and the data would never have arrived.
func (s *Service) validate(in domain.Record, isCreate bool) (domain.Record, error) {
//
// The identity is a parameter because "the server will supply this column"
// is not a property of the column alone: a talent-only derivation supplies it
// for a talent caller and for nobody else. See serverSupplies.
func (s *Service) validate(ident authctx.Identity, in domain.Record, isCreate bool) (domain.Record, error) {
details := map[string]string{}
out := make(domain.Record, len(in))
@@ -237,7 +241,7 @@ func (s *Service) validate(in domain.Record, isCreate bool) (domain.Record, erro
if !col.Required {
continue
}
if s.serverSupplies(col.Name) {
if s.serverSupplies(col.Name, ident) {
// The repository fills this from the session, so demanding it
// from the caller would reject a request the server is about to
// complete correctly. evidence.worker_email is the live case.
@@ -262,13 +266,24 @@ func (s *Service) validate(in domain.Record, isCreate bool) (domain.Record, erro
}
// serverSupplies reports whether a column is filled in from the authenticated
// session rather than from the request body.
func (s *Service) serverSupplies(name string) bool {
// session rather than from the request body, FOR THIS CALLER.
//
// The caller matters. A TalentOnly derivation records who the row is ABOUT, and
// the repository fills it for a talent caller only — when an operator files an
// application or logs evidence on somebody else's behalf, the subject is not
// the operator, so nothing is derived and the value has to come from the body.
// Treating those columns as server-supplied for every role was how an operator
// creating a job application without an email got as far as SQL and came back
// with a not-null violation instead of the required-field message the contract
// promises. It must agree with repo.derivedValues, which decides the same thing
// on the write path.
func (s *Service) serverSupplies(name string, ident authctx.Identity) bool {
if s.res.Policy == nil {
return false
}
isTalent := ident.Role == string(domain.RoleTalent)
for _, d := range s.res.Policy.Derived {
if d.Column == name {
if d.Column == name && (!d.TalentOnly || isTalent) {
return true
}
}