mirror of https://github.com/vernonkeenan/lib
parent
abc0ef7918
commit
2da20d2d25
19
README.md
19
README.md
|
|
@ -51,7 +51,7 @@ pins the same module, a `lib` bump is a constellation-wide rebuild (KV-C6a).
|
||||||
| `app/service-helpers.go` | Pointer helpers (`String`/`Bool`/`Int64`/…), `GetFieldsAndValues` reflection helper (unit-tested) |
|
| `app/service-helpers.go` | Pointer helpers (`String`/`Bool`/`Int64`/…), `GetFieldsAndValues` reflection helper (unit-tested) |
|
||||||
| `app/user.go`, `user-helpers.go`, `tenantuser.go`, `userrole.go`, `address.go` | Compatibility principal/domain structs. ADR-KV-024 adds `PrincipalKey`, `PrincipalType`, exact `Scopes`, `HasScope`, and `IsServicePrincipal`; no native response carries its bearer secret. |
|
| `app/user.go`, `user-helpers.go`, `tenantuser.go`, `userrole.go`, `address.go` | Compatibility principal/domain structs. ADR-KV-024 adds `PrincipalKey`, `PrincipalType`, exact `Scopes`, `HasScope`, and `IsServicePrincipal`; no native response carries its bearer secret. |
|
||||||
| `app/logger/logger.go` | Thin `zap.SugaredLogger` wrapper (`New(level)`, level constants) |
|
| `app/logger/logger.go` | Thin `zap.SugaredLogger` wrapper (`New(level)`, level constants) |
|
||||||
| `api/{auth,crm,members,plex,research,sfgate,stash}/` | go-swagger–generated typed clients + models, one directory per sibling service. Stash is intentionally generated from the read-only PDF metadata projection described below. Research CompanyProduct/CompanyService operations are pinned to provider PR #32 as documented in `docs/RESEARCH_COMPANY_CATALOG_CLIENT.md`. |
|
| `api/{auth,crm,members,plex,research,sfgate,stash}/` | go-swagger–generated typed clients + models, one directory per sibling service. Stash is intentionally generated from the read-only PDF metadata projection described below. Research CompanyProduct/CompanyService operations are pinned to PR #57 source `c3127f32872051b842c74ae7139b1c6ef71e2c53`, merge `cc7bf6191dc105969c804e123823186f1ea26cc3`, and spec SHA-256 `1e5b34b5c7b4230cfd507995ab1f837aabc7b4dcdf61b114f37012167afdf224` as documented in `docs/RESEARCH_COMPANY_CATALOG_CLIENT.md`. |
|
||||||
| `swagger/*.yaml`, `swagger/defs/`, `swagger/external/` | Copies of each sibling service's spec (the KV-C6b spec-copy problem — no sync mechanism besides `make regen`), shared component defs, and host/path-rewritten copies for external doc publishing; also carries legacy vendored Kazoo/Clerk specs from `lib`'s pre-mesh history |
|
| `swagger/*.yaml`, `swagger/defs/`, `swagger/external/` | Copies of each sibling service's spec (the KV-C6b spec-copy problem — no sync mechanism besides `make regen`), shared component defs, and host/path-rewritten copies for external doc publishing; also carries legacy vendored Kazoo/Clerk specs from `lib`'s pre-mesh history |
|
||||||
|
|
||||||
## Build, run, test
|
## Build, run, test
|
||||||
|
|
@ -89,13 +89,16 @@ fields; it cannot generate the provider's deprecated, fail-closed create
|
||||||
compatibility route. See `docs/STASH_PDF_METADATA_CLIENT.md` for the provider
|
compatibility route. See `docs/STASH_PDF_METADATA_CLIENT.md` for the provider
|
||||||
commit and release blockers.
|
commit and release blockers.
|
||||||
|
|
||||||
The Research specification is synchronized from provider PR #32 at commit
|
The Research specification is synchronized from PR #57 source
|
||||||
`ca6a2911ce79d053f9aa338e6d9bcfe3357b0c77`. Its generated company catalog
|
`c3127f32872051b842c74ae7139b1c6ef71e2c53`, merged as
|
||||||
surface exposes Product and Service list/detail/create plus Service CAS update.
|
`cc7bf6191dc105969c804e123823186f1ea26cc3`. Its generated company catalog
|
||||||
Product direct update remains proposal-only, and both catalog deletes are
|
surface exposes Product and Service list/detail/create plus optimistic-
|
||||||
absent. See `docs/RESEARCH_COMPANY_CATALOG_CLIENT.md` for the pinned spec hash,
|
concurrency Product and Service updates. Published Product changes remain
|
||||||
exact scope requirements, database assumptions, and Research-before-Lib-before-
|
proposal-only, legacy proposal candidates are never silently converted to
|
||||||
Studio release gate.
|
direct writes, and both catalog deletes are absent. See
|
||||||
|
`docs/RESEARCH_COMPANY_CATALOG_CLIENT.md` for the pinned spec hash, exact scope
|
||||||
|
requirements, database assumptions, and Research-before-Lib-before-Studio
|
||||||
|
release gate.
|
||||||
|
|
||||||
**Known gap (resolved for the current spec set, but can recur):** if any
|
**Known gap (resolved for the current spec set, but can recur):** if any
|
||||||
sibling spec has an operation with no top-level `tags:`, go-swagger routes
|
sibling spec has an operation with no top-level `tags:`, go-swagger routes
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ func (transport *catalogCaptureTransport) SubmitContext(
|
||||||
return company_products.NewGetCompanyProductsOK(), nil
|
return company_products.NewGetCompanyProductsOK(), nil
|
||||||
case "postCompanyProducts":
|
case "postCompanyProducts":
|
||||||
return company_products.NewPostCompanyProductsOK(), nil
|
return company_products.NewPostCompanyProductsOK(), nil
|
||||||
|
case "putCompanyProduct":
|
||||||
|
return company_products.NewPutCompanyProductOK(), nil
|
||||||
case "getCompanyServices":
|
case "getCompanyServices":
|
||||||
return company_services.NewGetCompanyServicesOK(), nil
|
return company_services.NewGetCompanyServicesOK(), nil
|
||||||
case "postCompanyServices":
|
case "postCompanyServices":
|
||||||
|
|
@ -74,6 +76,15 @@ func TestGeneratedCompanyCatalogOperationContract(t *testing.T) {
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "CAS update product", wantID: "putCompanyProduct",
|
||||||
|
wantMethod: "PUT", wantPath: "/companyproducts",
|
||||||
|
call: func(transport openapiruntime.ContextualTransport) error {
|
||||||
|
_, err := company_products.New(transport, strfmt.Default).
|
||||||
|
PutCompanyProduct(company_products.NewPutCompanyProductParams(), nil)
|
||||||
|
return err
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "list or get service", wantID: "getCompanyServices",
|
name: "list or get service", wantID: "getCompanyServices",
|
||||||
wantMethod: "GET", wantPath: "/companyservices",
|
wantMethod: "GET", wantPath: "/companyservices",
|
||||||
|
|
@ -143,6 +154,10 @@ func TestGeneratedCompanyCatalogListGetAndMutationShapes(t *testing.T) {
|
||||||
WithCompanyProductRequest(productRequest).CompanyProductRequest; got != productRequest {
|
WithCompanyProductRequest(productRequest).CompanyProductRequest; got != productRequest {
|
||||||
t.Fatal("CompanyProduct create request body is absent")
|
t.Fatal("CompanyProduct create request body is absent")
|
||||||
}
|
}
|
||||||
|
if got := company_products.NewPutCompanyProductParams().
|
||||||
|
WithCompanyProductRequest(productRequest).CompanyProductRequest; got != productRequest {
|
||||||
|
t.Fatal("CompanyProduct CAS update request body is absent")
|
||||||
|
}
|
||||||
|
|
||||||
serviceRequest := &research_models.CompanyServiceRequest{
|
serviceRequest := &research_models.CompanyServiceRequest{
|
||||||
Data: []*research_models.CompanyService{{
|
Data: []*research_models.CompanyService{{
|
||||||
|
|
@ -161,24 +176,32 @@ func TestGeneratedCompanyCatalogListGetAndMutationShapes(t *testing.T) {
|
||||||
|
|
||||||
func TestGeneratedCompanyCatalogNegativeMutationResponses(t *testing.T) {
|
func TestGeneratedCompanyCatalogNegativeMutationResponses(t *testing.T) {
|
||||||
for name, response := range map[string]interface{ IsCode(int) bool }{
|
for name, response := range map[string]interface{ IsCode(int) bool }{
|
||||||
"product unauthorized": company_products.NewPostCompanyProductsUnauthorized(),
|
"product unauthorized": company_products.NewPostCompanyProductsUnauthorized(),
|
||||||
"product forbidden": company_products.NewPostCompanyProductsForbidden(),
|
"product forbidden": company_products.NewPostCompanyProductsForbidden(),
|
||||||
"product not found": company_products.NewPostCompanyProductsNotFound(),
|
"product not found": company_products.NewPostCompanyProductsNotFound(),
|
||||||
"product invalid": company_products.NewPostCompanyProductsUnprocessableEntity(),
|
"product invalid": company_products.NewPostCompanyProductsUnprocessableEntity(),
|
||||||
"service unauthorized": company_services.NewPostCompanyServicesUnauthorized(),
|
"product update unauthorized": company_products.NewPutCompanyProductUnauthorized(),
|
||||||
"service forbidden": company_services.NewPostCompanyServicesForbidden(),
|
"product update forbidden": company_products.NewPutCompanyProductForbidden(),
|
||||||
"service invalid": company_services.NewPostCompanyServicesUnprocessableEntity(),
|
"product update not found": company_products.NewPutCompanyProductNotFound(),
|
||||||
"update unauthorized": company_services.NewPutCompanyServiceUnauthorized(),
|
"product update conflict": company_products.NewPutCompanyProductConflict(),
|
||||||
"update forbidden": company_services.NewPutCompanyServiceForbidden(),
|
"product update invalid": company_products.NewPutCompanyProductUnprocessableEntity(),
|
||||||
"update not found": company_services.NewPutCompanyServiceNotFound(),
|
"service unauthorized": company_services.NewPostCompanyServicesUnauthorized(),
|
||||||
"update conflict": company_services.NewPutCompanyServiceConflict(),
|
"service forbidden": company_services.NewPostCompanyServicesForbidden(),
|
||||||
"update invalid": company_services.NewPutCompanyServiceUnprocessableEntity(),
|
"service invalid": company_services.NewPostCompanyServicesUnprocessableEntity(),
|
||||||
|
"update unauthorized": company_services.NewPutCompanyServiceUnauthorized(),
|
||||||
|
"update forbidden": company_services.NewPutCompanyServiceForbidden(),
|
||||||
|
"update not found": company_services.NewPutCompanyServiceNotFound(),
|
||||||
|
"update conflict": company_services.NewPutCompanyServiceConflict(),
|
||||||
|
"update invalid": company_services.NewPutCompanyServiceUnprocessableEntity(),
|
||||||
} {
|
} {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
expected := map[string]int{
|
expected := map[string]int{
|
||||||
"product unauthorized": 401, "product forbidden": 403,
|
"product unauthorized": 401, "product forbidden": 403,
|
||||||
"product not found": 404, "product invalid": 422,
|
"product not found": 404, "product invalid": 422,
|
||||||
"service unauthorized": 401, "service forbidden": 403,
|
"product update unauthorized": 401, "product update forbidden": 403,
|
||||||
|
"product update not found": 404, "product update conflict": 409,
|
||||||
|
"product update invalid": 422,
|
||||||
|
"service unauthorized": 401, "service forbidden": 403,
|
||||||
"service invalid": 422, "update unauthorized": 401,
|
"service invalid": 422, "update unauthorized": 401,
|
||||||
"update forbidden": 403, "update not found": 404,
|
"update forbidden": 403, "update not found": 404,
|
||||||
"update conflict": 409, "update invalid": 422,
|
"update conflict": 409, "update invalid": 422,
|
||||||
|
|
@ -193,7 +216,6 @@ func TestGeneratedCompanyCatalogNegativeMutationResponses(t *testing.T) {
|
||||||
func TestGeneratedCompanyCatalogDoesNotExposeUnsafeMutations(t *testing.T) {
|
func TestGeneratedCompanyCatalogDoesNotExposeUnsafeMutations(t *testing.T) {
|
||||||
productContract := reflect.TypeOf((*company_products.ClientService)(nil)).Elem()
|
productContract := reflect.TypeOf((*company_products.ClientService)(nil)).Elem()
|
||||||
for _, method := range []string{
|
for _, method := range []string{
|
||||||
"PutCompanyProduct", "PutCompanyProductContext",
|
|
||||||
"DeleteCompanyProduct", "DeleteCompanyProductContext",
|
"DeleteCompanyProduct", "DeleteCompanyProductContext",
|
||||||
} {
|
} {
|
||||||
if _, exists := productContract.MethodByName(method); exists {
|
if _, exists := productContract.MethodByName(method); exists {
|
||||||
|
|
@ -217,11 +239,18 @@ func TestCompanyCatalogProviderProjectionRequiresCompoundAuth(t *testing.T) {
|
||||||
}
|
}
|
||||||
products := document.Spec().Paths.Paths["/companyproducts"]
|
products := document.Spec().Paths.Paths["/companyproducts"]
|
||||||
services := document.Spec().Paths.Paths["/companyservices"]
|
services := document.Spec().Paths.Paths["/companyservices"]
|
||||||
|
if products.Put == nil {
|
||||||
|
t.Fatal("provider projection is missing CompanyProduct CAS update")
|
||||||
|
}
|
||||||
|
if services.Put == nil {
|
||||||
|
t.Fatal("provider projection is missing CompanyService CAS update")
|
||||||
|
}
|
||||||
operations := []*struct {
|
operations := []*struct {
|
||||||
Security []map[string][]string
|
Security []map[string][]string
|
||||||
}{
|
}{
|
||||||
{Security: products.Get.Security},
|
{Security: products.Get.Security},
|
||||||
{Security: products.Post.Security},
|
{Security: products.Post.Security},
|
||||||
|
{Security: products.Put.Security},
|
||||||
{Security: services.Get.Security},
|
{Security: services.Get.Security},
|
||||||
{Security: services.Post.Security},
|
{Security: services.Post.Security},
|
||||||
{Security: services.Put.Security},
|
{Security: services.Put.Security},
|
||||||
|
|
@ -237,8 +266,21 @@ func TestCompanyCatalogProviderProjectionRequiresCompoundAuth(t *testing.T) {
|
||||||
t.Fatal("catalog operation is missing kvSessionCookie")
|
t.Fatal("catalog operation is missing kvSessionCookie")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if products.Put != nil || products.Delete != nil || services.Delete != nil {
|
for _, fragment := range []string{
|
||||||
t.Fatal("provider projection reintroduced Product PUT or a catalog DELETE")
|
"optimistic concurrency",
|
||||||
|
"preserving its immutable Account binding",
|
||||||
|
"publication state",
|
||||||
|
"enrichment audit",
|
||||||
|
"media ownership",
|
||||||
|
"Published Products require the governed proposal workflow",
|
||||||
|
"research:company-product:update",
|
||||||
|
} {
|
||||||
|
if !strings.Contains(products.Put.Description, fragment) {
|
||||||
|
t.Errorf("CompanyProduct PUT description is missing %q", fragment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if products.Delete != nil || services.Delete != nil {
|
||||||
|
t.Fatal("provider projection exposes a catalog DELETE")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,12 @@ type ClientService interface {
|
||||||
// PostCompanyProductsContext create one tenant owned company product.
|
// PostCompanyProductsContext create one tenant owned company product.
|
||||||
PostCompanyProductsContext(ctx context.Context, params *PostCompanyProductsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*PostCompanyProductsOK, error)
|
PostCompanyProductsContext(ctx context.Context, params *PostCompanyProductsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*PostCompanyProductsOK, error)
|
||||||
|
|
||||||
|
// PutCompanyProduct update one unpublished shared catalog company product.
|
||||||
|
PutCompanyProduct(params *PutCompanyProductParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*PutCompanyProductOK, error)
|
||||||
|
|
||||||
|
// PutCompanyProductContext update one unpublished shared catalog company product.
|
||||||
|
PutCompanyProductContext(ctx context.Context, params *PutCompanyProductParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*PutCompanyProductOK, error)
|
||||||
|
|
||||||
SetTransport(transport runtime.ContextualTransport)
|
SetTransport(transport runtime.ContextualTransport)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -217,7 +223,7 @@ func (a *Client) GetPublishedCompanyProductsContext(ctx context.Context, params
|
||||||
|
|
||||||
// PostCompanyProducts creates one tenant owned company product.
|
// PostCompanyProducts creates one tenant owned company product.
|
||||||
//
|
//
|
||||||
// Create one unpublished CompanyProduct beneath an Account owned by the machine tenant; requires research:company-product:create and same-tenant Owner or Manager. Existing Product updates remain proposal-only..
|
// Create one unpublished CompanyProduct beneath an Account owned by the machine tenant; requires research:company-product:create and same-tenant Owner or Manager.
|
||||||
//
|
//
|
||||||
// This method does not support injected context.
|
// This method does not support injected context.
|
||||||
// However, timeout and opentracing contexts are honored whenever enabled.
|
// However, timeout and opentracing contexts are honored whenever enabled.
|
||||||
|
|
@ -236,7 +242,7 @@ func (a *Client) PostCompanyProducts(params *PostCompanyProductsParams, authInfo
|
||||||
|
|
||||||
// PostCompanyProductsContext creates one tenant owned company product.
|
// PostCompanyProductsContext creates one tenant owned company product.
|
||||||
//
|
//
|
||||||
// Create one unpublished CompanyProduct beneath an Account owned by the machine tenant; requires research:company-product:create and same-tenant Owner or Manager. Existing Product updates remain proposal-only..
|
// Create one unpublished CompanyProduct beneath an Account owned by the machine tenant; requires research:company-product:create and same-tenant Owner or Manager.
|
||||||
//
|
//
|
||||||
// Do not use the deprecated [PostCompanyProductsParams.Context] with this method: it would be ignored.
|
// Do not use the deprecated [PostCompanyProductsParams.Context] with this method: it would be ignored.
|
||||||
func (a *Client) PostCompanyProductsContext(ctx context.Context, params *PostCompanyProductsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*PostCompanyProductsOK, error) {
|
func (a *Client) PostCompanyProductsContext(ctx context.Context, params *PostCompanyProductsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*PostCompanyProductsOK, error) {
|
||||||
|
|
@ -282,6 +288,73 @@ func (a *Client) PostCompanyProductsContext(ctx context.Context, params *PostCom
|
||||||
panic(msg)
|
panic(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PutCompanyProduct updates one unpublished shared catalog company product.
|
||||||
|
//
|
||||||
|
// Replace the editable fields of one shared-catalog CompanyProduct using optimistic concurrency while preserving its immutable Account binding, publication state, enrichment audit, and media ownership. Published Products require the governed proposal workflow. Requires research:company-product:update and a same-tenant Owner or Manager..
|
||||||
|
//
|
||||||
|
// This method does not support injected context.
|
||||||
|
// However, timeout and opentracing contexts are honored whenever enabled.
|
||||||
|
//
|
||||||
|
// If you need to pass a specific context, use [Client.PutCompanyProductContext] instead.
|
||||||
|
func (a *Client) PutCompanyProduct(params *PutCompanyProductParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*PutCompanyProductOK, error) {
|
||||||
|
var ctx context.Context
|
||||||
|
if params.inner.ctx != nil {
|
||||||
|
ctx = params.inner.ctx
|
||||||
|
} else {
|
||||||
|
ctx = context.Background()
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.PutCompanyProductContext(ctx, params, authInfo, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutCompanyProductContext updates one unpublished shared catalog company product.
|
||||||
|
//
|
||||||
|
// Replace the editable fields of one shared-catalog CompanyProduct using optimistic concurrency while preserving its immutable Account binding, publication state, enrichment audit, and media ownership. Published Products require the governed proposal workflow. Requires research:company-product:update and a same-tenant Owner or Manager..
|
||||||
|
//
|
||||||
|
// Do not use the deprecated [PutCompanyProductParams.Context] with this method: it would be ignored.
|
||||||
|
func (a *Client) PutCompanyProductContext(ctx context.Context, params *PutCompanyProductParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*PutCompanyProductOK, error) {
|
||||||
|
// NOTE: parameters are not validated before sending
|
||||||
|
if params == nil {
|
||||||
|
params = NewPutCompanyProductParams()
|
||||||
|
}
|
||||||
|
|
||||||
|
op := &runtime.ClientOperation{
|
||||||
|
ID: "putCompanyProduct",
|
||||||
|
Method: "PUT",
|
||||||
|
PathPattern: "/companyproducts",
|
||||||
|
ProducesMediaTypes: []string{"application/json"},
|
||||||
|
ConsumesMediaTypes: []string{"application/json"},
|
||||||
|
Schemes: []string{"http"},
|
||||||
|
Params: params,
|
||||||
|
Reader: &PutCompanyProductReader{formats: a.formats},
|
||||||
|
AuthInfo: authInfo,
|
||||||
|
Client: params.HTTPClient,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(op)
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := a.transport.SubmitContext(ctx, op)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// only one success response has to be checked
|
||||||
|
success, ok := result.(*PutCompanyProductOK)
|
||||||
|
if ok {
|
||||||
|
return success, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// unexpected success response.
|
||||||
|
|
||||||
|
// no default response is defined.
|
||||||
|
//
|
||||||
|
// safeguard: normally, in the absence of a default response, unknown success responses return an error above: so this is a codegen issue
|
||||||
|
msg := fmt.Sprintf("unexpected success response for putCompanyProduct: API contract not enforced by server. Client expected to get an error, but got: %T", result)
|
||||||
|
panic(msg)
|
||||||
|
}
|
||||||
|
|
||||||
// SetTransport changes the transport on the client
|
// SetTransport changes the transport on the client
|
||||||
func (a *Client) SetTransport(transport runtime.ContextualTransport) {
|
func (a *Client) SetTransport(transport runtime.ContextualTransport) {
|
||||||
a.transport = transport
|
a.transport = transport
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,159 @@
|
||||||
|
// Code generated by go-swagger; DO NOT EDIT.
|
||||||
|
|
||||||
|
// (c) 2012-2020 by Taxnexus, Inc.
|
||||||
|
// All rights reserved worldwide.
|
||||||
|
// Proprietary product; unlicensed use is not allowed
|
||||||
|
|
||||||
|
package company_products
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"code.tnxs.net/vernonkeenan/lib/api/research/research_models"
|
||||||
|
"github.com/go-openapi/errors"
|
||||||
|
"github.com/go-openapi/runtime"
|
||||||
|
cr "github.com/go-openapi/runtime/client"
|
||||||
|
"github.com/go-openapi/strfmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewPutCompanyProductParams creates a new PutCompanyProductParams object,
|
||||||
|
// with the default timeout for this client.
|
||||||
|
//
|
||||||
|
// Default values are not hydrated, since defaults are normally applied by the API server side.
|
||||||
|
//
|
||||||
|
// To enforce default values in parameter, use SetDefaults or WithDefaults.
|
||||||
|
func NewPutCompanyProductParams() *PutCompanyProductParams {
|
||||||
|
return NewPutCompanyProductParamsWithTimeout(cr.DefaultTimeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPutCompanyProductParamsWithTimeout creates a new PutCompanyProductParams object
|
||||||
|
// with the ability to set a timeout on a request.
|
||||||
|
func NewPutCompanyProductParamsWithTimeout(timeout time.Duration) *PutCompanyProductParams {
|
||||||
|
return &PutCompanyProductParams{
|
||||||
|
inner: innerParams{
|
||||||
|
timeout: timeout,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPutCompanyProductParamsWithContext creates a new PutCompanyProductParams object
|
||||||
|
// with the ability to set a context for a request.
|
||||||
|
//
|
||||||
|
// Deprecated: use the operation call with context to pass the context instead of [PutCompanyProductParams].
|
||||||
|
func NewPutCompanyProductParamsWithContext(ctx context.Context) *PutCompanyProductParams {
|
||||||
|
return &PutCompanyProductParams{
|
||||||
|
inner: innerParams{
|
||||||
|
ctx: ctx,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPutCompanyProductParamsWithHTTPClient creates a new PutCompanyProductParams object
|
||||||
|
// with the ability to set a custom HTTPClient for a request.
|
||||||
|
func NewPutCompanyProductParamsWithHTTPClient(client *http.Client) *PutCompanyProductParams {
|
||||||
|
return &PutCompanyProductParams{
|
||||||
|
HTTPClient: client,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
PutCompanyProductParams contains all the parameters to send to the API endpoint
|
||||||
|
|
||||||
|
for the put company product operation.
|
||||||
|
|
||||||
|
Typically these are written to a http.Request.
|
||||||
|
*/
|
||||||
|
type PutCompanyProductParams struct {
|
||||||
|
|
||||||
|
// CompanyProductRequest.
|
||||||
|
//
|
||||||
|
// An array of new CompanyProduct records
|
||||||
|
CompanyProductRequest *research_models.CompanyProductRequest
|
||||||
|
|
||||||
|
HTTPClient *http.Client
|
||||||
|
|
||||||
|
inner innerParams
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDefaults hydrates default values in the put company product params (not the query body).
|
||||||
|
//
|
||||||
|
// All values with no default are reset to their zero value.
|
||||||
|
func (o *PutCompanyProductParams) WithDefaults() *PutCompanyProductParams {
|
||||||
|
o.SetDefaults()
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDefaults hydrates default values in the put company product params (not the query body).
|
||||||
|
//
|
||||||
|
// All values with no default are reset to their zero value.
|
||||||
|
func (o *PutCompanyProductParams) SetDefaults() {
|
||||||
|
// no default values defined for this parameter
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTimeout adds the timeout to the put company product params.
|
||||||
|
func (o *PutCompanyProductParams) WithTimeout(timeout time.Duration) *PutCompanyProductParams {
|
||||||
|
o.SetTimeout(timeout)
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTimeout adds the timeout to the put company product params.
|
||||||
|
func (o *PutCompanyProductParams) SetTimeout(timeout time.Duration) {
|
||||||
|
o.inner.timeout = timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithContext adds the context to the put company product params.
|
||||||
|
//
|
||||||
|
// Deprecated: use the operation call with context to pass the context instead of [PutCompanyProductParams].
|
||||||
|
func (o *PutCompanyProductParams) WithContext(ctx context.Context) *PutCompanyProductParams {
|
||||||
|
o.SetContext(ctx)
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetContext adds the context to the put company product params.
|
||||||
|
//
|
||||||
|
// Deprecated: use the operation call with context to pass the context instead of [PutCompanyProductParams].
|
||||||
|
func (o *PutCompanyProductParams) SetContext(ctx context.Context) {
|
||||||
|
o.inner.ctx = ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithHTTPClient adds the HTTPClient to the put company product params.
|
||||||
|
func (o *PutCompanyProductParams) WithHTTPClient(client *http.Client) *PutCompanyProductParams {
|
||||||
|
o.SetHTTPClient(client)
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHTTPClient adds the HTTPClient to the put company product params.
|
||||||
|
func (o *PutCompanyProductParams) SetHTTPClient(client *http.Client) {
|
||||||
|
o.HTTPClient = client
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithCompanyProductRequest adds the companyProductRequest to the put company product params.
|
||||||
|
func (o *PutCompanyProductParams) WithCompanyProductRequest(companyProductRequest *research_models.CompanyProductRequest) *PutCompanyProductParams {
|
||||||
|
o.SetCompanyProductRequest(companyProductRequest)
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetCompanyProductRequest adds the companyProductRequest to the put company product params.
|
||||||
|
func (o *PutCompanyProductParams) SetCompanyProductRequest(companyProductRequest *research_models.CompanyProductRequest) {
|
||||||
|
o.CompanyProductRequest = companyProductRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteToRequest writes these params to a [runtime.ClientRequest].
|
||||||
|
func (o *PutCompanyProductParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
|
||||||
|
if err := r.SetTimeout(o.inner.timeout); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var res []error
|
||||||
|
if o.CompanyProductRequest != nil {
|
||||||
|
if err := r.SetBodyParam(o.CompanyProductRequest); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res) > 0 {
|
||||||
|
return errors.CompositeValidationError(res...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,603 @@
|
||||||
|
// Code generated by go-swagger; DO NOT EDIT.
|
||||||
|
|
||||||
|
// (c) 2012-2020 by Taxnexus, Inc.
|
||||||
|
// All rights reserved worldwide.
|
||||||
|
// Proprietary product; unlicensed use is not allowed
|
||||||
|
|
||||||
|
package company_products
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
stderrors "errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"code.tnxs.net/vernonkeenan/lib/api/research/research_models"
|
||||||
|
"github.com/go-openapi/runtime"
|
||||||
|
"github.com/go-openapi/strfmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PutCompanyProductReader is a Reader for the PutCompanyProduct structure.
|
||||||
|
type PutCompanyProductReader struct {
|
||||||
|
formats strfmt.Registry
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadResponse reads a server response into the received o.
|
||||||
|
func (o *PutCompanyProductReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (any, error) {
|
||||||
|
switch response.Code() {
|
||||||
|
case 200:
|
||||||
|
result := NewPutCompanyProductOK()
|
||||||
|
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
case 401:
|
||||||
|
result := NewPutCompanyProductUnauthorized()
|
||||||
|
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nil, result
|
||||||
|
case 403:
|
||||||
|
result := NewPutCompanyProductForbidden()
|
||||||
|
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nil, result
|
||||||
|
case 404:
|
||||||
|
result := NewPutCompanyProductNotFound()
|
||||||
|
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nil, result
|
||||||
|
case 409:
|
||||||
|
result := NewPutCompanyProductConflict()
|
||||||
|
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nil, result
|
||||||
|
case 422:
|
||||||
|
result := NewPutCompanyProductUnprocessableEntity()
|
||||||
|
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nil, result
|
||||||
|
case 500:
|
||||||
|
result := NewPutCompanyProductInternalServerError()
|
||||||
|
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nil, result
|
||||||
|
default:
|
||||||
|
return nil, runtime.NewAPIError("[PUT /companyproducts] putCompanyProduct", response, response.Code())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPutCompanyProductOK creates a PutCompanyProductOK with default headers values
|
||||||
|
func NewPutCompanyProductOK() *PutCompanyProductOK {
|
||||||
|
return &PutCompanyProductOK{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutCompanyProductOK describes a response with status code 200, with default header values.
|
||||||
|
//
|
||||||
|
// Response with CompanyProduct objects
|
||||||
|
type PutCompanyProductOK struct {
|
||||||
|
Payload *research_models.CompanyProductResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSuccess returns true when this put company product o k response has a 2xx status code
|
||||||
|
func (o *PutCompanyProductOK) IsSuccess() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRedirect returns true when this put company product o k response has a 3xx status code
|
||||||
|
func (o *PutCompanyProductOK) IsRedirect() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsClientError returns true when this put company product o k response has a 4xx status code
|
||||||
|
func (o *PutCompanyProductOK) IsClientError() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsServerError returns true when this put company product o k response has a 5xx status code
|
||||||
|
func (o *PutCompanyProductOK) IsServerError() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCode returns true when this put company product o k response a status code equal to that given
|
||||||
|
func (o *PutCompanyProductOK) IsCode(code int) bool {
|
||||||
|
return code == 200
|
||||||
|
}
|
||||||
|
|
||||||
|
// Code gets the status code for the put company product o k response
|
||||||
|
func (o *PutCompanyProductOK) Code() int {
|
||||||
|
return 200
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductOK) Error() string {
|
||||||
|
payload, _ := json.Marshal(o.Payload)
|
||||||
|
return fmt.Sprintf("[PUT /companyproducts][%d] putCompanyProductOK %s", 200, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductOK) String() string {
|
||||||
|
payload, _ := json.Marshal(o.Payload)
|
||||||
|
return fmt.Sprintf("[PUT /companyproducts][%d] putCompanyProductOK %s", 200, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductOK) GetPayload() *research_models.CompanyProductResponse {
|
||||||
|
return o.Payload
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
o.Payload = new(research_models.CompanyProductResponse)
|
||||||
|
|
||||||
|
// response payload
|
||||||
|
if err := consumer.Consume(response.Body(), o.Payload); err != nil && !stderrors.Is(err, io.EOF) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPutCompanyProductUnauthorized creates a PutCompanyProductUnauthorized with default headers values
|
||||||
|
func NewPutCompanyProductUnauthorized() *PutCompanyProductUnauthorized {
|
||||||
|
return &PutCompanyProductUnauthorized{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutCompanyProductUnauthorized describes a response with status code 401, with default header values.
|
||||||
|
//
|
||||||
|
// Access unauthorized, invalid API-KEY was used
|
||||||
|
type PutCompanyProductUnauthorized struct {
|
||||||
|
AccessControlAllowOrigin string
|
||||||
|
|
||||||
|
Payload *research_models.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSuccess returns true when this put company product unauthorized response has a 2xx status code
|
||||||
|
func (o *PutCompanyProductUnauthorized) IsSuccess() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRedirect returns true when this put company product unauthorized response has a 3xx status code
|
||||||
|
func (o *PutCompanyProductUnauthorized) IsRedirect() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsClientError returns true when this put company product unauthorized response has a 4xx status code
|
||||||
|
func (o *PutCompanyProductUnauthorized) IsClientError() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsServerError returns true when this put company product unauthorized response has a 5xx status code
|
||||||
|
func (o *PutCompanyProductUnauthorized) IsServerError() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCode returns true when this put company product unauthorized response a status code equal to that given
|
||||||
|
func (o *PutCompanyProductUnauthorized) IsCode(code int) bool {
|
||||||
|
return code == 401
|
||||||
|
}
|
||||||
|
|
||||||
|
// Code gets the status code for the put company product unauthorized response
|
||||||
|
func (o *PutCompanyProductUnauthorized) Code() int {
|
||||||
|
return 401
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductUnauthorized) Error() string {
|
||||||
|
payload, _ := json.Marshal(o.Payload)
|
||||||
|
return fmt.Sprintf("[PUT /companyproducts][%d] putCompanyProductUnauthorized %s", 401, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductUnauthorized) String() string {
|
||||||
|
payload, _ := json.Marshal(o.Payload)
|
||||||
|
return fmt.Sprintf("[PUT /companyproducts][%d] putCompanyProductUnauthorized %s", 401, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductUnauthorized) GetPayload() *research_models.Error {
|
||||||
|
return o.Payload
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductUnauthorized) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
// hydrates response header Access-Control-Allow-Origin
|
||||||
|
hdrAccessControlAllowOrigin := response.GetHeader("Access-Control-Allow-Origin")
|
||||||
|
|
||||||
|
if hdrAccessControlAllowOrigin != "" {
|
||||||
|
o.AccessControlAllowOrigin = hdrAccessControlAllowOrigin
|
||||||
|
}
|
||||||
|
|
||||||
|
o.Payload = new(research_models.Error)
|
||||||
|
|
||||||
|
// response payload
|
||||||
|
if err := consumer.Consume(response.Body(), o.Payload); err != nil && !stderrors.Is(err, io.EOF) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPutCompanyProductForbidden creates a PutCompanyProductForbidden with default headers values
|
||||||
|
func NewPutCompanyProductForbidden() *PutCompanyProductForbidden {
|
||||||
|
return &PutCompanyProductForbidden{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutCompanyProductForbidden describes a response with status code 403, with default header values.
|
||||||
|
//
|
||||||
|
// Access forbidden, account lacks access
|
||||||
|
type PutCompanyProductForbidden struct {
|
||||||
|
AccessControlAllowOrigin string
|
||||||
|
|
||||||
|
Payload *research_models.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSuccess returns true when this put company product forbidden response has a 2xx status code
|
||||||
|
func (o *PutCompanyProductForbidden) IsSuccess() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRedirect returns true when this put company product forbidden response has a 3xx status code
|
||||||
|
func (o *PutCompanyProductForbidden) IsRedirect() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsClientError returns true when this put company product forbidden response has a 4xx status code
|
||||||
|
func (o *PutCompanyProductForbidden) IsClientError() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsServerError returns true when this put company product forbidden response has a 5xx status code
|
||||||
|
func (o *PutCompanyProductForbidden) IsServerError() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCode returns true when this put company product forbidden response a status code equal to that given
|
||||||
|
func (o *PutCompanyProductForbidden) IsCode(code int) bool {
|
||||||
|
return code == 403
|
||||||
|
}
|
||||||
|
|
||||||
|
// Code gets the status code for the put company product forbidden response
|
||||||
|
func (o *PutCompanyProductForbidden) Code() int {
|
||||||
|
return 403
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductForbidden) Error() string {
|
||||||
|
payload, _ := json.Marshal(o.Payload)
|
||||||
|
return fmt.Sprintf("[PUT /companyproducts][%d] putCompanyProductForbidden %s", 403, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductForbidden) String() string {
|
||||||
|
payload, _ := json.Marshal(o.Payload)
|
||||||
|
return fmt.Sprintf("[PUT /companyproducts][%d] putCompanyProductForbidden %s", 403, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductForbidden) GetPayload() *research_models.Error {
|
||||||
|
return o.Payload
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductForbidden) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
// hydrates response header Access-Control-Allow-Origin
|
||||||
|
hdrAccessControlAllowOrigin := response.GetHeader("Access-Control-Allow-Origin")
|
||||||
|
|
||||||
|
if hdrAccessControlAllowOrigin != "" {
|
||||||
|
o.AccessControlAllowOrigin = hdrAccessControlAllowOrigin
|
||||||
|
}
|
||||||
|
|
||||||
|
o.Payload = new(research_models.Error)
|
||||||
|
|
||||||
|
// response payload
|
||||||
|
if err := consumer.Consume(response.Body(), o.Payload); err != nil && !stderrors.Is(err, io.EOF) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPutCompanyProductNotFound creates a PutCompanyProductNotFound with default headers values
|
||||||
|
func NewPutCompanyProductNotFound() *PutCompanyProductNotFound {
|
||||||
|
return &PutCompanyProductNotFound{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutCompanyProductNotFound describes a response with status code 404, with default header values.
|
||||||
|
//
|
||||||
|
// Resource was not found
|
||||||
|
type PutCompanyProductNotFound struct {
|
||||||
|
AccessControlAllowOrigin string
|
||||||
|
|
||||||
|
Payload *research_models.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSuccess returns true when this put company product not found response has a 2xx status code
|
||||||
|
func (o *PutCompanyProductNotFound) IsSuccess() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRedirect returns true when this put company product not found response has a 3xx status code
|
||||||
|
func (o *PutCompanyProductNotFound) IsRedirect() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsClientError returns true when this put company product not found response has a 4xx status code
|
||||||
|
func (o *PutCompanyProductNotFound) IsClientError() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsServerError returns true when this put company product not found response has a 5xx status code
|
||||||
|
func (o *PutCompanyProductNotFound) IsServerError() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCode returns true when this put company product not found response a status code equal to that given
|
||||||
|
func (o *PutCompanyProductNotFound) IsCode(code int) bool {
|
||||||
|
return code == 404
|
||||||
|
}
|
||||||
|
|
||||||
|
// Code gets the status code for the put company product not found response
|
||||||
|
func (o *PutCompanyProductNotFound) Code() int {
|
||||||
|
return 404
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductNotFound) Error() string {
|
||||||
|
payload, _ := json.Marshal(o.Payload)
|
||||||
|
return fmt.Sprintf("[PUT /companyproducts][%d] putCompanyProductNotFound %s", 404, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductNotFound) String() string {
|
||||||
|
payload, _ := json.Marshal(o.Payload)
|
||||||
|
return fmt.Sprintf("[PUT /companyproducts][%d] putCompanyProductNotFound %s", 404, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductNotFound) GetPayload() *research_models.Error {
|
||||||
|
return o.Payload
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductNotFound) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
// hydrates response header Access-Control-Allow-Origin
|
||||||
|
hdrAccessControlAllowOrigin := response.GetHeader("Access-Control-Allow-Origin")
|
||||||
|
|
||||||
|
if hdrAccessControlAllowOrigin != "" {
|
||||||
|
o.AccessControlAllowOrigin = hdrAccessControlAllowOrigin
|
||||||
|
}
|
||||||
|
|
||||||
|
o.Payload = new(research_models.Error)
|
||||||
|
|
||||||
|
// response payload
|
||||||
|
if err := consumer.Consume(response.Body(), o.Payload); err != nil && !stderrors.Is(err, io.EOF) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPutCompanyProductConflict creates a PutCompanyProductConflict with default headers values
|
||||||
|
func NewPutCompanyProductConflict() *PutCompanyProductConflict {
|
||||||
|
return &PutCompanyProductConflict{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutCompanyProductConflict describes a response with status code 409, with default header values.
|
||||||
|
//
|
||||||
|
// Conflict
|
||||||
|
type PutCompanyProductConflict struct {
|
||||||
|
AccessControlAllowOrigin string
|
||||||
|
|
||||||
|
Payload *research_models.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSuccess returns true when this put company product conflict response has a 2xx status code
|
||||||
|
func (o *PutCompanyProductConflict) IsSuccess() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRedirect returns true when this put company product conflict response has a 3xx status code
|
||||||
|
func (o *PutCompanyProductConflict) IsRedirect() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsClientError returns true when this put company product conflict response has a 4xx status code
|
||||||
|
func (o *PutCompanyProductConflict) IsClientError() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsServerError returns true when this put company product conflict response has a 5xx status code
|
||||||
|
func (o *PutCompanyProductConflict) IsServerError() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCode returns true when this put company product conflict response a status code equal to that given
|
||||||
|
func (o *PutCompanyProductConflict) IsCode(code int) bool {
|
||||||
|
return code == 409
|
||||||
|
}
|
||||||
|
|
||||||
|
// Code gets the status code for the put company product conflict response
|
||||||
|
func (o *PutCompanyProductConflict) Code() int {
|
||||||
|
return 409
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductConflict) Error() string {
|
||||||
|
payload, _ := json.Marshal(o.Payload)
|
||||||
|
return fmt.Sprintf("[PUT /companyproducts][%d] putCompanyProductConflict %s", 409, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductConflict) String() string {
|
||||||
|
payload, _ := json.Marshal(o.Payload)
|
||||||
|
return fmt.Sprintf("[PUT /companyproducts][%d] putCompanyProductConflict %s", 409, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductConflict) GetPayload() *research_models.Error {
|
||||||
|
return o.Payload
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductConflict) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
// hydrates response header Access-Control-Allow-Origin
|
||||||
|
hdrAccessControlAllowOrigin := response.GetHeader("Access-Control-Allow-Origin")
|
||||||
|
|
||||||
|
if hdrAccessControlAllowOrigin != "" {
|
||||||
|
o.AccessControlAllowOrigin = hdrAccessControlAllowOrigin
|
||||||
|
}
|
||||||
|
|
||||||
|
o.Payload = new(research_models.Error)
|
||||||
|
|
||||||
|
// response payload
|
||||||
|
if err := consumer.Consume(response.Body(), o.Payload); err != nil && !stderrors.Is(err, io.EOF) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPutCompanyProductUnprocessableEntity creates a PutCompanyProductUnprocessableEntity with default headers values
|
||||||
|
func NewPutCompanyProductUnprocessableEntity() *PutCompanyProductUnprocessableEntity {
|
||||||
|
return &PutCompanyProductUnprocessableEntity{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutCompanyProductUnprocessableEntity describes a response with status code 422, with default header values.
|
||||||
|
//
|
||||||
|
// Unprocessable Entity, likely a bad parameter
|
||||||
|
type PutCompanyProductUnprocessableEntity struct {
|
||||||
|
AccessControlAllowOrigin string
|
||||||
|
|
||||||
|
Payload *research_models.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSuccess returns true when this put company product unprocessable entity response has a 2xx status code
|
||||||
|
func (o *PutCompanyProductUnprocessableEntity) IsSuccess() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRedirect returns true when this put company product unprocessable entity response has a 3xx status code
|
||||||
|
func (o *PutCompanyProductUnprocessableEntity) IsRedirect() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsClientError returns true when this put company product unprocessable entity response has a 4xx status code
|
||||||
|
func (o *PutCompanyProductUnprocessableEntity) IsClientError() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsServerError returns true when this put company product unprocessable entity response has a 5xx status code
|
||||||
|
func (o *PutCompanyProductUnprocessableEntity) IsServerError() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCode returns true when this put company product unprocessable entity response a status code equal to that given
|
||||||
|
func (o *PutCompanyProductUnprocessableEntity) IsCode(code int) bool {
|
||||||
|
return code == 422
|
||||||
|
}
|
||||||
|
|
||||||
|
// Code gets the status code for the put company product unprocessable entity response
|
||||||
|
func (o *PutCompanyProductUnprocessableEntity) Code() int {
|
||||||
|
return 422
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductUnprocessableEntity) Error() string {
|
||||||
|
payload, _ := json.Marshal(o.Payload)
|
||||||
|
return fmt.Sprintf("[PUT /companyproducts][%d] putCompanyProductUnprocessableEntity %s", 422, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductUnprocessableEntity) String() string {
|
||||||
|
payload, _ := json.Marshal(o.Payload)
|
||||||
|
return fmt.Sprintf("[PUT /companyproducts][%d] putCompanyProductUnprocessableEntity %s", 422, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductUnprocessableEntity) GetPayload() *research_models.Error {
|
||||||
|
return o.Payload
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductUnprocessableEntity) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
// hydrates response header Access-Control-Allow-Origin
|
||||||
|
hdrAccessControlAllowOrigin := response.GetHeader("Access-Control-Allow-Origin")
|
||||||
|
|
||||||
|
if hdrAccessControlAllowOrigin != "" {
|
||||||
|
o.AccessControlAllowOrigin = hdrAccessControlAllowOrigin
|
||||||
|
}
|
||||||
|
|
||||||
|
o.Payload = new(research_models.Error)
|
||||||
|
|
||||||
|
// response payload
|
||||||
|
if err := consumer.Consume(response.Body(), o.Payload); err != nil && !stderrors.Is(err, io.EOF) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPutCompanyProductInternalServerError creates a PutCompanyProductInternalServerError with default headers values
|
||||||
|
func NewPutCompanyProductInternalServerError() *PutCompanyProductInternalServerError {
|
||||||
|
return &PutCompanyProductInternalServerError{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutCompanyProductInternalServerError describes a response with status code 500, with default header values.
|
||||||
|
//
|
||||||
|
// Server Internal Error
|
||||||
|
type PutCompanyProductInternalServerError struct {
|
||||||
|
AccessControlAllowOrigin string
|
||||||
|
|
||||||
|
Payload *research_models.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSuccess returns true when this put company product internal server error response has a 2xx status code
|
||||||
|
func (o *PutCompanyProductInternalServerError) IsSuccess() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRedirect returns true when this put company product internal server error response has a 3xx status code
|
||||||
|
func (o *PutCompanyProductInternalServerError) IsRedirect() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsClientError returns true when this put company product internal server error response has a 4xx status code
|
||||||
|
func (o *PutCompanyProductInternalServerError) IsClientError() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsServerError returns true when this put company product internal server error response has a 5xx status code
|
||||||
|
func (o *PutCompanyProductInternalServerError) IsServerError() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCode returns true when this put company product internal server error response a status code equal to that given
|
||||||
|
func (o *PutCompanyProductInternalServerError) IsCode(code int) bool {
|
||||||
|
return code == 500
|
||||||
|
}
|
||||||
|
|
||||||
|
// Code gets the status code for the put company product internal server error response
|
||||||
|
func (o *PutCompanyProductInternalServerError) Code() int {
|
||||||
|
return 500
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductInternalServerError) Error() string {
|
||||||
|
payload, _ := json.Marshal(o.Payload)
|
||||||
|
return fmt.Sprintf("[PUT /companyproducts][%d] putCompanyProductInternalServerError %s", 500, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductInternalServerError) String() string {
|
||||||
|
payload, _ := json.Marshal(o.Payload)
|
||||||
|
return fmt.Sprintf("[PUT /companyproducts][%d] putCompanyProductInternalServerError %s", 500, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductInternalServerError) GetPayload() *research_models.Error {
|
||||||
|
return o.Payload
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *PutCompanyProductInternalServerError) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||||
|
|
||||||
|
// hydrates response header Access-Control-Allow-Origin
|
||||||
|
hdrAccessControlAllowOrigin := response.GetHeader("Access-Control-Allow-Origin")
|
||||||
|
|
||||||
|
if hdrAccessControlAllowOrigin != "" {
|
||||||
|
o.AccessControlAllowOrigin = hdrAccessControlAllowOrigin
|
||||||
|
}
|
||||||
|
|
||||||
|
o.Payload = new(research_models.Error)
|
||||||
|
|
||||||
|
// response payload
|
||||||
|
if err := consumer.Consume(response.Body(), o.Payload); err != nil && !stderrors.Is(err, io.EOF) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -21,7 +21,7 @@ import (
|
||||||
"github.com/go-openapi/strfmt"
|
"github.com/go-openapi/strfmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
const researchProviderSpecSHA256 = "7385c249c9f24d4b1dd4bfd5c1c067c8288bb5b590c72ac9daef5009dc5db0ac"
|
const researchProviderSpecSHA256 = "1e5b34b5c7b4230cfd507995ab1f837aabc7b4dcdf61b114f37012167afdf224"
|
||||||
|
|
||||||
type insightCaptureTransport struct {
|
type insightCaptureTransport struct {
|
||||||
operation *openapiruntime.ClientOperation
|
operation *openapiruntime.ClientOperation
|
||||||
|
|
|
||||||
|
|
@ -290,7 +290,7 @@ func (a *Client) PostPortfolioEnrichmentRunContext(ctx context.Context, params *
|
||||||
|
|
||||||
// PostPortfolioReconciliation reconciles one portfolio candidate in discovery mode.
|
// PostPortfolioReconciliation reconciles one portfolio candidate in discovery mode.
|
||||||
//
|
//
|
||||||
// Create exactly one authoritative Product or Service, or compare-and-swap update one authoritative Service, from one immutable direct-write candidate in a completed same-tenant portfolio_enrichment.v1 run. This Discovery-only operation requires an active server-side tenant policy for the exact entity action, the matching create or update scope, an active Owner or Manager session, explicit acknowledgement, and an idempotency key. Operator-selected field values remain distinct from immutable candidate provenance. Existing Product changes remain governed proposals. It never deletes, creates relationships, proposes, reviews, applies, or publishes..
|
// Create or compare-and-swap update exactly one authoritative Product or Service from one immutable direct-write candidate in a completed same-tenant portfolio_enrichment.v1 run. This Discovery-only operation requires an active server-side tenant policy for the exact entity action, the matching create or update scope, an active Owner or Manager session, explicit acknowledgement, and an idempotency key. Operator-selected field values remain distinct from immutable candidate provenance. Legacy Product governed-update candidates are not silently converted to direct writes and must be rerun. It never deletes, creates relationships, proposes, reviews, applies, or publishes..
|
||||||
//
|
//
|
||||||
// This method does not support injected context.
|
// This method does not support injected context.
|
||||||
// However, timeout and opentracing contexts are honored whenever enabled.
|
// However, timeout and opentracing contexts are honored whenever enabled.
|
||||||
|
|
@ -309,7 +309,7 @@ func (a *Client) PostPortfolioReconciliation(params *PostPortfolioReconciliation
|
||||||
|
|
||||||
// PostPortfolioReconciliationContext reconciles one portfolio candidate in discovery mode.
|
// PostPortfolioReconciliationContext reconciles one portfolio candidate in discovery mode.
|
||||||
//
|
//
|
||||||
// Create exactly one authoritative Product or Service, or compare-and-swap update one authoritative Service, from one immutable direct-write candidate in a completed same-tenant portfolio_enrichment.v1 run. This Discovery-only operation requires an active server-side tenant policy for the exact entity action, the matching create or update scope, an active Owner or Manager session, explicit acknowledgement, and an idempotency key. Operator-selected field values remain distinct from immutable candidate provenance. Existing Product changes remain governed proposals. It never deletes, creates relationships, proposes, reviews, applies, or publishes..
|
// Create or compare-and-swap update exactly one authoritative Product or Service from one immutable direct-write candidate in a completed same-tenant portfolio_enrichment.v1 run. This Discovery-only operation requires an active server-side tenant policy for the exact entity action, the matching create or update scope, an active Owner or Manager session, explicit acknowledgement, and an idempotency key. Operator-selected field values remain distinct from immutable candidate provenance. Legacy Product governed-update candidates are not silently converted to direct writes and must be rerun. It never deletes, creates relationships, proposes, reviews, applies, or publishes..
|
||||||
//
|
//
|
||||||
// Do not use the deprecated [PostPortfolioReconciliationParams.Context] with this method: it would be ignored.
|
// Do not use the deprecated [PostPortfolioReconciliationParams.Context] with this method: it would be ignored.
|
||||||
func (a *Client) PostPortfolioReconciliationContext(ctx context.Context, params *PostPortfolioReconciliationParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*PostPortfolioReconciliationOK, error) {
|
func (a *Client) PostPortfolioReconciliationContext(ctx context.Context, params *PostPortfolioReconciliationParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*PostPortfolioReconciliationOK, error) {
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,21 @@ func TestGeneratedServiceUpdateReceiptCarriesBeforeAndResultVersions(t *testing.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPortfolioReconciliationContractKeepsProductUpdatesGoverned(t *testing.T) {
|
func TestGeneratedProductUpdateReconciliationRequestShape(t *testing.T) {
|
||||||
|
request := validProductUpdateReconciliationRequest()
|
||||||
|
if err := request.Validate(strfmt.Default); err != nil {
|
||||||
|
t.Fatalf("valid Product update request failed generated validation: %v", err)
|
||||||
|
}
|
||||||
|
if got := *request.Action; got != research_models.PortfolioReconciliationRequestActionUpdate {
|
||||||
|
t.Errorf("Action = %q, want update", got)
|
||||||
|
}
|
||||||
|
if got := *request.EntityType; got !=
|
||||||
|
research_models.PortfolioReconciliationRequestEntityTypeCompanyProduct {
|
||||||
|
t.Errorf("EntityType = %q, want company_product", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPortfolioReconciliationSupportsProductUpdatesWithoutConvertingLegacyRuns(t *testing.T) {
|
||||||
document, err := loads.Spec(filepath.Join(
|
document, err := loads.Spec(filepath.Join(
|
||||||
portfolioReconciliationRepoRoot(t), "swagger", "research-vernonkeenan.yaml",
|
portfolioReconciliationRepoRoot(t), "swagger", "research-vernonkeenan.yaml",
|
||||||
))
|
))
|
||||||
|
|
@ -195,15 +209,21 @@ func TestPortfolioReconciliationContractKeepsProductUpdatesGoverned(t *testing.T
|
||||||
}
|
}
|
||||||
if !strings.Contains(
|
if !strings.Contains(
|
||||||
reconciliation.Post.Description,
|
reconciliation.Post.Description,
|
||||||
"Existing Product changes remain governed proposals",
|
"Create or compare-and-swap update exactly one authoritative Product or Service",
|
||||||
) {
|
) {
|
||||||
t.Fatal("reconciliation contract does not preserve Product update rejection")
|
t.Fatal("reconciliation contract does not expose Product direct update")
|
||||||
}
|
}
|
||||||
if document.Spec().Paths.Paths["/companyproducts"].Put != nil {
|
if !strings.Contains(
|
||||||
t.Fatal("provider projection exposes a direct CompanyProduct PUT")
|
reconciliation.Post.Description,
|
||||||
|
"Legacy Product governed-update candidates are not silently converted to direct writes",
|
||||||
|
) {
|
||||||
|
t.Fatal("reconciliation contract does not keep legacy Product runs fail-closed")
|
||||||
|
}
|
||||||
|
if document.Spec().Paths.Paths["/companyproducts"].Put == nil {
|
||||||
|
t.Fatal("provider projection is missing direct CompanyProduct PUT")
|
||||||
}
|
}
|
||||||
if _, ok := reconciliation.Post.Responses.StatusCodeResponses[422]; !ok {
|
if _, ok := reconciliation.Post.Responses.StatusCodeResponses[422]; !ok {
|
||||||
t.Fatal("reconciliation contract does not expose invalid Product update rejection")
|
t.Fatal("reconciliation contract does not expose invalid or legacy Product update rejection")
|
||||||
}
|
}
|
||||||
if !portfolio_enrichment_runs.
|
if !portfolio_enrichment_runs.
|
||||||
NewPostPortfolioReconciliationUnprocessableEntity().
|
NewPostPortfolioReconciliationUnprocessableEntity().
|
||||||
|
|
@ -256,6 +276,15 @@ func validServiceUpdateReconciliationRequest() *research_models.PortfolioReconci
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validProductUpdateReconciliationRequest() *research_models.PortfolioReconciliationRequest {
|
||||||
|
request := validServiceUpdateReconciliationRequest()
|
||||||
|
entityType := research_models.PortfolioReconciliationRequestEntityTypeCompanyProduct
|
||||||
|
idempotencyKey := "studio-product-update-0001"
|
||||||
|
request.EntityType = &entityType
|
||||||
|
request.IdempotencyKey = &idempotencyKey
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
func portfolioReconciliationRepoRoot(t *testing.T) string {
|
func portfolioReconciliationRepoRoot(t *testing.T) string {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
_, testFile, _, ok := runtime.Caller(0)
|
_, testFile, _, ok := runtime.Caller(0)
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
# Research company catalog client
|
# Research company catalog client
|
||||||
|
|
||||||
This slice synchronizes the full Research provider specification from
|
This slice synchronizes the full Research provider specification from PR #57
|
||||||
`vernonkeenan/research` draft PR #32 at provider commit
|
source commit `c3127f32872051b842c74ae7139b1c6ef71e2c53`, merged to Research `main`
|
||||||
`ca6a2911ce79d053f9aa338e6d9bcfe3357b0c77`. The pinned internal spec SHA-256
|
as `cc7bf6191dc105969c804e123823186f1ea26cc3`. The pinned internal spec
|
||||||
is `c213fe19077453fcdc8f8ce3f6d1671cbbb5074f348c9e4ee0739f64ab0ebba3`;
|
SHA-256 is `1e5b34b5c7b4230cfd507995ab1f837aabc7b4dcdf61b114f37012167afdf224`;
|
||||||
the external copy differs only by Lib's conventional scheme, host, and base
|
the external copy differs only by Lib's conventional scheme, host, and base
|
||||||
path rewrite.
|
path rewrite.
|
||||||
|
|
||||||
|
|
@ -11,7 +11,9 @@ The generated CompanyProduct surface contains:
|
||||||
|
|
||||||
- shared list/detail through `GET /companyproducts`;
|
- shared list/detail through `GET /companyproducts`;
|
||||||
- safe tenant-attributed create through `POST /companyproducts`; and
|
- safe tenant-attributed create through `POST /companyproducts`; and
|
||||||
- no direct update or delete.
|
- optimistic-concurrency update of unpublished Products through
|
||||||
|
`PUT /companyproducts`; and
|
||||||
|
- no delete.
|
||||||
|
|
||||||
The generated CompanyService surface contains:
|
The generated CompanyService surface contains:
|
||||||
|
|
||||||
|
|
@ -26,26 +28,33 @@ Every operation retains one compound security alternative containing both
|
||||||
forwards only the `kvSession` cookie. Credential values do not enter the
|
forwards only the `kvSession` cookie. Credential values do not enter the
|
||||||
generated models, source, tests, or logs.
|
generated models, source, tests, or logs.
|
||||||
|
|
||||||
Product update remains intentionally proposal-only. The separate generated
|
Published Product update remains intentionally proposal-only. The separate
|
||||||
proposal client records, submits, and independently reviews Product changes;
|
generated proposal client records, submits, and independently reviews Product
|
||||||
review does not itself apply or publish the authoritative Product. This Lib
|
changes; review does not itself apply or publish the authoritative Product.
|
||||||
|
Discovery reconciliation may update an unpublished Product, but legacy
|
||||||
|
governed-update candidates remain fail-closed and must be rerun rather than
|
||||||
|
silently converted. The Product PUT contract preserves immutable Account
|
||||||
|
binding, publication state, enrichment audit, and media ownership. This Lib
|
||||||
slice does not invent application, publication, bulk, media-ownership, or
|
slice does not invent application, publication, bulk, media-ownership, or
|
||||||
delete operations.
|
delete operations.
|
||||||
|
|
||||||
## Dependency and release gate
|
## Dependency and release gate
|
||||||
|
|
||||||
This Lib PR may be reviewed while Research PR #32 is open, but it must not be
|
This Lib PR may be reviewed while the Research Product-update change is open,
|
||||||
released until:
|
but it must not be released until:
|
||||||
|
|
||||||
1. Research PR #32 is merged, released, and deployed;
|
1. Research merge `cc7bf6191dc105969c804e123823186f1ea26cc3` is
|
||||||
|
released and deployed;
|
||||||
2. the KV Studio native service principal has the exact governed scopes
|
2. the KV Studio native service principal has the exact governed scopes
|
||||||
`research:company-product:read`, `research:company-product:create`,
|
`research:company-product:read`, `research:company-product:create`,
|
||||||
|
`research:company-product:update`,
|
||||||
`research:company-service:read`, `research:company-service:create`, and
|
`research:company-service:read`, `research:company-service:create`, and
|
||||||
`research:company-service:update`;
|
`research:company-service:update`;
|
||||||
3. Research production smoke tests prove the native catalog paths and zero
|
3. Research production smoke tests prove the native catalog paths and zero
|
||||||
Salesforce reads or writes; and
|
Salesforce reads or writes; and
|
||||||
4. KV Studio is ready to pin the new Lib tag, preserve the Product proposal
|
4. KV Studio is ready to pin the new Lib tag, preserve the Product proposal
|
||||||
workflow, and run its Playwright list/detail/create/Service-edit coverage.
|
workflow for governed and published changes, and run its Playwright
|
||||||
|
list/detail/create/Product-edit/Service-edit coverage.
|
||||||
|
|
||||||
There is no database migration in this client slice. Research remains
|
There is no database migration in this client slice. Research remains
|
||||||
responsible for proving ownership through the existing
|
responsible for proving ownership through the existing
|
||||||
|
|
|
||||||
|
|
@ -585,7 +585,7 @@ paths:
|
||||||
tags:
|
tags:
|
||||||
- CompanyProducts
|
- CompanyProducts
|
||||||
post:
|
post:
|
||||||
description: Create one unpublished CompanyProduct beneath an Account owned by the machine tenant; requires research:company-product:create and same-tenant Owner or Manager. Existing Product updates remain proposal-only.
|
description: Create one unpublished CompanyProduct beneath an Account owned by the machine tenant; requires research:company-product:create and same-tenant Owner or Manager
|
||||||
operationId: postCompanyProducts
|
operationId: postCompanyProducts
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: "#/parameters/companyProductRequest"
|
- $ref: "#/parameters/companyProductRequest"
|
||||||
|
|
@ -608,6 +608,32 @@ paths:
|
||||||
summary: Create one tenant-owned CompanyProduct
|
summary: Create one tenant-owned CompanyProduct
|
||||||
tags:
|
tags:
|
||||||
- CompanyProducts
|
- CompanyProducts
|
||||||
|
put:
|
||||||
|
description: Replace the editable fields of one shared-catalog CompanyProduct using optimistic concurrency while preserving its immutable Account binding, publication state, enrichment audit, and media ownership. Published Products require the governed proposal workflow. Requires research:company-product:update and a same-tenant Owner or Manager.
|
||||||
|
operationId: putCompanyProduct
|
||||||
|
parameters:
|
||||||
|
- $ref: "#/parameters/companyProductRequest"
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
$ref: "#/responses/CompanyProductResponse"
|
||||||
|
"401":
|
||||||
|
$ref: "#/responses/Unauthorized"
|
||||||
|
"403":
|
||||||
|
$ref: "#/responses/AccessForbidden"
|
||||||
|
"404":
|
||||||
|
$ref: "#/responses/NotFound"
|
||||||
|
"409":
|
||||||
|
$ref: "#/responses/Conflict"
|
||||||
|
"422":
|
||||||
|
$ref: "#/responses/UnprocessableEntity"
|
||||||
|
"500":
|
||||||
|
$ref: "#/responses/ServerError"
|
||||||
|
security:
|
||||||
|
- ApiKeyAuth: []
|
||||||
|
kvSessionCookie: []
|
||||||
|
summary: Update one unpublished shared-catalog CompanyProduct
|
||||||
|
tags:
|
||||||
|
- CompanyProducts
|
||||||
/publishedcompanyproducts:
|
/publishedcompanyproducts:
|
||||||
get:
|
get:
|
||||||
description: Return only published CompanyProducts whose owning CRM Account is also published; requires a tenant-bound native service principal with the exact research:company-product:public-read scope and does not accept a human session
|
description: Return only published CompanyProducts whose owning CRM Account is also published; requires a tenant-bound native service principal with the exact research:company-product:public-read scope and does not accept a human session
|
||||||
|
|
@ -1008,7 +1034,7 @@ paths:
|
||||||
- PortfolioEnrichmentRuns
|
- PortfolioEnrichmentRuns
|
||||||
/portfolioenrichmentruns/{portfolioEnrichmentRunId}/reconciliations:
|
/portfolioenrichmentruns/{portfolioEnrichmentRunId}/reconciliations:
|
||||||
post:
|
post:
|
||||||
description: Create exactly one authoritative Product or Service, or compare-and-swap update one authoritative Service, from one immutable direct-write candidate in a completed same-tenant portfolio_enrichment.v1 run. This Discovery-only operation requires an active server-side tenant policy for the exact entity action, the matching create or update scope, an active Owner or Manager session, explicit acknowledgement, and an idempotency key. Operator-selected field values remain distinct from immutable candidate provenance. Existing Product changes remain governed proposals. It never deletes, creates relationships, proposes, reviews, applies, or publishes.
|
description: Create or compare-and-swap update exactly one authoritative Product or Service from one immutable direct-write candidate in a completed same-tenant portfolio_enrichment.v1 run. This Discovery-only operation requires an active server-side tenant policy for the exact entity action, the matching create or update scope, an active Owner or Manager session, explicit acknowledgement, and an idempotency key. Operator-selected field values remain distinct from immutable candidate provenance. Legacy Product governed-update candidates are not silently converted to direct writes and must be rerun. It never deletes, creates relationships, proposes, reviews, applies, or publishes.
|
||||||
operationId: postPortfolioReconciliation
|
operationId: postPortfolioReconciliation
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: "#/parameters/portfolioEnrichmentRunIdPath"
|
- $ref: "#/parameters/portfolioEnrichmentRunIdPath"
|
||||||
|
|
|
||||||
|
|
@ -585,7 +585,7 @@ paths:
|
||||||
tags:
|
tags:
|
||||||
- CompanyProducts
|
- CompanyProducts
|
||||||
post:
|
post:
|
||||||
description: Create one unpublished CompanyProduct beneath an Account owned by the machine tenant; requires research:company-product:create and same-tenant Owner or Manager. Existing Product updates remain proposal-only.
|
description: Create one unpublished CompanyProduct beneath an Account owned by the machine tenant; requires research:company-product:create and same-tenant Owner or Manager
|
||||||
operationId: postCompanyProducts
|
operationId: postCompanyProducts
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: "#/parameters/companyProductRequest"
|
- $ref: "#/parameters/companyProductRequest"
|
||||||
|
|
@ -608,6 +608,32 @@ paths:
|
||||||
summary: Create one tenant-owned CompanyProduct
|
summary: Create one tenant-owned CompanyProduct
|
||||||
tags:
|
tags:
|
||||||
- CompanyProducts
|
- CompanyProducts
|
||||||
|
put:
|
||||||
|
description: Replace the editable fields of one shared-catalog CompanyProduct using optimistic concurrency while preserving its immutable Account binding, publication state, enrichment audit, and media ownership. Published Products require the governed proposal workflow. Requires research:company-product:update and a same-tenant Owner or Manager.
|
||||||
|
operationId: putCompanyProduct
|
||||||
|
parameters:
|
||||||
|
- $ref: "#/parameters/companyProductRequest"
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
$ref: "#/responses/CompanyProductResponse"
|
||||||
|
"401":
|
||||||
|
$ref: "#/responses/Unauthorized"
|
||||||
|
"403":
|
||||||
|
$ref: "#/responses/AccessForbidden"
|
||||||
|
"404":
|
||||||
|
$ref: "#/responses/NotFound"
|
||||||
|
"409":
|
||||||
|
$ref: "#/responses/Conflict"
|
||||||
|
"422":
|
||||||
|
$ref: "#/responses/UnprocessableEntity"
|
||||||
|
"500":
|
||||||
|
$ref: "#/responses/ServerError"
|
||||||
|
security:
|
||||||
|
- ApiKeyAuth: []
|
||||||
|
kvSessionCookie: []
|
||||||
|
summary: Update one unpublished shared-catalog CompanyProduct
|
||||||
|
tags:
|
||||||
|
- CompanyProducts
|
||||||
/publishedcompanyproducts:
|
/publishedcompanyproducts:
|
||||||
get:
|
get:
|
||||||
description: Return only published CompanyProducts whose owning CRM Account is also published; requires a tenant-bound native service principal with the exact research:company-product:public-read scope and does not accept a human session
|
description: Return only published CompanyProducts whose owning CRM Account is also published; requires a tenant-bound native service principal with the exact research:company-product:public-read scope and does not accept a human session
|
||||||
|
|
@ -1008,7 +1034,7 @@ paths:
|
||||||
- PortfolioEnrichmentRuns
|
- PortfolioEnrichmentRuns
|
||||||
/portfolioenrichmentruns/{portfolioEnrichmentRunId}/reconciliations:
|
/portfolioenrichmentruns/{portfolioEnrichmentRunId}/reconciliations:
|
||||||
post:
|
post:
|
||||||
description: Create exactly one authoritative Product or Service, or compare-and-swap update one authoritative Service, from one immutable direct-write candidate in a completed same-tenant portfolio_enrichment.v1 run. This Discovery-only operation requires an active server-side tenant policy for the exact entity action, the matching create or update scope, an active Owner or Manager session, explicit acknowledgement, and an idempotency key. Operator-selected field values remain distinct from immutable candidate provenance. Existing Product changes remain governed proposals. It never deletes, creates relationships, proposes, reviews, applies, or publishes.
|
description: Create or compare-and-swap update exactly one authoritative Product or Service from one immutable direct-write candidate in a completed same-tenant portfolio_enrichment.v1 run. This Discovery-only operation requires an active server-side tenant policy for the exact entity action, the matching create or update scope, an active Owner or Manager session, explicit acknowledgement, and an idempotency key. Operator-selected field values remain distinct from immutable candidate provenance. Legacy Product governed-update candidates are not silently converted to direct writes and must be rerun. It never deletes, creates relationships, proposes, reviews, applies, or publishes.
|
||||||
operationId: postPortfolioReconciliation
|
operationId: postPortfolioReconciliation
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: "#/parameters/portfolioEnrichmentRunIdPath"
|
- $ref: "#/parameters/portfolioEnrichmentRunIdPath"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue