Make cookie banner origin immutable after creation

Origin is a fundamental identity property of a banner tied to consent
records for a specific site. Changing it would break the audit trail
and violate GDPR consent specificity requirements.

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-04-24 17:46:00 +04:00
parent 4ec075fa80
commit 11f856740a
5 changed files with 1 additions and 16 deletions

View File

@@ -40,7 +40,6 @@ const updateBannerMutation = graphql`
cookieBanner {
id
name
origin
privacyPolicyUrl
consentExpiryDays
consentMode
@@ -68,7 +67,6 @@ export function BannerSettingsForm({ cookieBannerKey }: BannerSettingsFormProps)
const [updateBanner, isUpdating] = useMutation<BannerSettingsFormMutation>(updateBannerMutation);
const [name, setName] = useState(banner.name);
const [origin, setOrigin] = useState(banner.origin);
const [privacyPolicyUrl, setPrivacyPolicyUrl] = useState(banner.privacyPolicyUrl);
const [consentExpiryDays, setConsentExpiryDays] = useState(String(banner.consentExpiryDays));
const [consentMode, setConsentMode] = useState(banner.consentMode);
@@ -82,7 +80,6 @@ export function BannerSettingsForm({ cookieBannerKey }: BannerSettingsFormProps)
input: {
cookieBannerId: banner.id,
name,
origin,
privacyPolicyUrl,
consentExpiryDays: parseInt(consentExpiryDays, 10),
consentMode: consentMode,
@@ -108,7 +105,7 @@ export function BannerSettingsForm({ cookieBannerKey }: BannerSettingsFormProps)
</Field>
<Field label={__("Origin URL")}>
<Input value={origin} onChange={e => setOrigin(e.target.value)} required />
<Input value={banner.origin} disabled />
</Field>
<Field label={__("Privacy Policy URL")}>

View File

@@ -61,7 +61,6 @@ type (
UpdateCookieBannerRequest struct {
CookieBannerID gid.GID
Name *string
Origin *string
PrivacyPolicyURL *string
ConsentExpiryDays *int
ConsentMode *coredata.CookieConsentMode
@@ -175,7 +174,6 @@ func (r *UpdateCookieBannerRequest) Validate() error {
v.Check(r.CookieBannerID, "cookie_banner_id", validator.Required(), validator.GID(coredata.CookieBannerEntityType))
v.Check(r.Name, "name", validator.SafeTextNoNewLine(255))
v.Check(r.Origin, "origin", validator.Origin())
v.Check(r.PrivacyPolicyURL, "privacy_policy_url", validator.URL())
v.Check(r.ConsentExpiryDays, "consent_expiry_days", validator.Min(1))
v.Check(r.ConsentMode, "consent_mode", validator.OneOfSlice(coredata.CookieConsentModes()))
@@ -775,9 +773,6 @@ func (s *Service) UpdateCookieBanner(
if req.Name != nil {
banner.Name = *req.Name
}
if req.Origin != nil {
banner.Origin = CanonicalizeOrigin(*req.Origin)
}
if req.PrivacyPolicyURL != nil {
banner.PrivacyPolicyURL = *req.PrivacyPolicyURL
}

View File

@@ -392,7 +392,6 @@ func (b *CookieBanner) Update(
UPDATE cookie_banners
SET
name = @name,
origin = @origin,
state = @state,
privacy_policy_url = @privacy_policy_url,
consent_expiry_days = @consent_expiry_days,
@@ -410,7 +409,6 @@ WHERE
args := pgx.StrictNamedArgs{
"id": b.ID,
"name": b.Name,
"origin": b.Origin,
"state": b.State,
"privacy_policy_url": b.PrivacyPolicyURL,
"consent_expiry_days": b.ConsentExpiryDays,

View File

@@ -269,7 +269,6 @@ func (r *mutationResolver) UpdateCookieBanner(ctx context.Context, input types.U
cookiebanner.UpdateCookieBannerRequest{
CookieBannerID: input.CookieBannerID,
Name: input.Name,
Origin: input.Origin,
PrivacyPolicyURL: input.PrivacyPolicyURL,
ConsentExpiryDays: input.ConsentExpiryDays,
ConsentMode: input.ConsentMode,
@@ -280,9 +279,6 @@ func (r *mutationResolver) UpdateCookieBanner(ctx context.Context, input types.U
if errors.Is(err, cookiebanner.ErrBannerNotFound) {
return nil, gqlutils.NotFound(ctx, err)
}
if errors.Is(err, cookiebanner.ErrOriginAlreadyInUse) {
return nil, gqlutils.Conflict(ctx, err)
}
if validationErrors, ok := errors.AsType[validator.ValidationErrors](err); ok {
return nil, gqlutils.InvalidValidationErrors(ctx, validationErrors)
}

View File

@@ -274,7 +274,6 @@ input CreateCookieBannerInput {
input UpdateCookieBannerInput {
cookieBannerId: ID!
name: String
origin: String
privacyPolicyUrl: String
consentExpiryDays: Int
consentMode: CookieConsentMode