Skip to content

Snowflake Marketplace Listing Playbook

Operational SOP for shipping new Marketplace listings or resubmitting after rejection. Distilled from 14+ manifest rejection cycles during the 2026-04-20→23 sprint, plus the 2026-04-28 real-data-leak incident and Paid bundle 510404 gate discovery.

This document is SSOT for execution. The Claude skill at .claude/skills/snowflake-listing-submit/ is a thin pointer to this file.

Prerequisites

  • Roles: account has split — ACCOUNTADMIN for CREATE SHARE and grants on share contents; ORGADMIN for CREATE EXTERNAL LISTING, ALTER LISTING, ALTER PROFILE. Multi-phase scripts must USE ROLE between phases or fail with "Insufficient privileges to operate on account".
  • Provider profile: must be APPROVED (or at least PENDING, not REJECTED) for any listing to publish. Profile lives in SNOWFLAKE_DATA_MARKETPLACE data exchange. Check via SHOW PROFILES IN DATA EXCHANGE SNOWFLAKE_DATA_MARKETPLACE.
  • Share: target share must exist with secure_objects_only = TRUE. Example: HUSKY_MOBILE_SAMPLE wraps views in HUSKY_DATA.SHARE.
  • Snowflake CLI (snow) configured against ~/.snowflake/connections.toml profile Husky (org=ciqcvik, account=ujb07324, region AWS_US_WEST_2). Snowsight Worksheets UI is brittle for paste-large-SQL — always prefer CLI for multi-statement scripts.
  • Account billing/service address = SG (151 Chin Swee Road, #07-12 Manhattan House, Singapore 169876) for any Paid listing. HK address triggers 510404 — see Failure Mode #2.

Inputs (gather before opening any SQL)

  • Listing identity: <NAME>, <TITLE>, <SUBTITLE ≤110 chars>
  • Access type: FREE | LIMITED_TRIAL | PAID (decide per § Access Type Decision Tree)
  • Share name: existing or new (if new, CREATE SHARE first under ACCOUNTADMIN)
  • Share contents: enumerate views/tables. Verify row counts vs access tier (see Failure Mode #1)
  • Trial duration (if LIMITED_TRIAL): one of 1 / 7 / 30 / 60 / 90 days
  • Pricing plan YAML (if PAID): pre-staged in @HUSKY_DATA.PUBLIC.LISTING_MANIFESTS/<folder>/
  • Geo coverage: countries list using Snowflake-canonical names (uppercase, human-readable; see § YAML schema)

Workflow

Phase 0 — Pre-flight (mandatory, no exceptions)

# 1. Confirm CLI connection works
snow sql --connection Husky -q "SELECT CURRENT_ACCOUNT(), CURRENT_REGION(), CURRENT_VERSION()"

# 2. Snapshot current listings state
snow sql --connection Husky --format json -q "USE ROLE ORGADMIN; SHOW LISTINGS;" \
  | python3 -c "
import json, sys
data = json.load(sys.stdin)
listings = data[1] if len(data) > 1 else data
for L in sorted(listings, key=lambda x: x['name']):
    print(f\"{L['name']:55} state={L.get('state','-'):10} review={L.get('review_state') or '-'}\")
"

# 3. For each share referenced, verify row counts match access tier
snow sql --connection Husky -q "
USE ROLE ACCOUNTADMIN;
USE DATABASE HUSKY_DATA; USE SCHEMA SHARE;
SELECT 'V_HEM_US_SAMPLE' v, COUNT(*) c FROM V_HEM_US_SAMPLE
UNION ALL SELECT 'V_MAID_APAC_PLUS_US_SAMPLE', COUNT(*) FROM V_MAID_APAC_PLUS_US_SAMPLE
UNION ALL SELECT 'SEGMENT_CATALOG', COUNT(*) FROM SEGMENT_CATALOG
;"

🛑 Hard stop: if any view bound to a Free/Trial share has row_count ≥ 10M, abort. See Failure Mode #1.

Phase 1 — Reverse-engineer schema before writing

Snowflake's manifest YAML has undocumented enum traps. Don't blind-guess:

./docs/internal/dump_listing_manifest.sh <ANY_EXISTING_LISTING> /tmp/baseline.yaml

Pulls the canonical YAML Snowflake stores. When making a change:

  1. Open Snowsight (as ORGADMIN), make the change in UI
  2. Re-run dump → /tmp/after.yaml
  3. diff /tmp/baseline.yaml /tmp/after.yaml → exact field name and shape

This pattern was the breakthrough for most of the sprint's schema traps. Also try WebFetch on docs.snowflake.com/en/progaccess/listing-manifest-reference — verified accessible 2026-04-25 (earlier "blocked" claim was wrong; always retry before guessing).

Phase 2 — Author the manifest

Write manifest to /tmp/lst<NN>-<purpose>.yaml. Do NOT inline manifest in CREATE statement until validated.

Minimal manifest skeleton (Free / Limited Trial; verified shape 2026-04-25):

title: "..."
subtitle: "..."  # ≤110 chars
description: |
  Multi-line markdown OK. NO TABLES (UI renders raw pipes).
  Use **bold** + bullets only.
profile: "<profile_name_exact_including_uuid>"
listing_terms:
  type: "STANDARD"          # STANDARD | CUSTOM | OFFLINE
categories:
  - MARKETING               # MARKETING | IDENTITY | ANALYTICS TOOLS | CORTEX AI READY
business_needs:
  - name: "Audience Activation"   # only confirmed-working enum value
    description: "..."
data_attributes:
  refresh_rate:
    update_frequency: MONTHLY    # HOURLY | DAILY | WEEKLY | MONTHLY | YEARLY | EVENT_BASED
  geography:
    geo_option: COUNTRIES        # NOT_APPLICABLE | GLOBAL | COUNTRIES
    granularity: [COUNTRY]       # COUNTRY | LATITUDE_LONGITUDE | ADDRESS | POSTAL_CODE | CITY | COUNTY | STATE | REGION_CONTINENT
    coverage:
      states: []                 # required field even when empty
      continents:
        ASIA: [HONG KONG, INDIA, JAPAN, SOUTH KOREA, SINGAPORE, MALAYSIA, INDONESIA, PHILIPPINES, THAILAND, VIETNAM]
        NORTH AMERICA: [UNITED STATES]
        OCEANIA: [AUSTRALIA, NEW ZEALAND]
usage_examples:
  - title: "..."
    description: "..."
    query: "SELECT * FROM SHARE.V_HEM_US_SAMPLE LIMIT 10;"   # 2-part name only
resources:
  documentation: "https://huskydata.io/products/<sku>"        # product-specific URL, not /segments

# For Limited Trial only:
limited_trial_plan:
  trial_time_limit: 30

For Paid, see § Paid Listing Path — different structure (manifest + pricing_plan files staged).

Phase 3 — Create or alter listing

New listing (under ORGADMIN):

USE ROLE ORGADMIN;
CREATE EXTERNAL LISTING <NAME>
  SHARE <SHARE_NAME>
  AS $$
  -- paste manifest YAML here, using $$ dollar-quotes (avoids apostrophe escaping)
  $$
  PUBLISH=FALSE REVIEW=FALSE;  -- DRAFT state, not yet submitted

Resubmit existing listing with revised manifest:

USE ROLE ORGADMIN;
ALTER LISTING <NAME>
  AS $$
  ...
  $$
  PUBLISH=TRUE REVIEW=TRUE;  -- submit for review + auto-publish on approval

🛑 The combo PUBLISH=TRUE REVIEW=FALSE always errors: "publish needs to be FALSE when requesting a listing to not be reviewed". Linked-boolean rule:

(PUBLISH, REVIEW) Effect
(FALSE, FALSE) DRAFT / unsubmitted
(FALSE, TRUE) Submit for review only — manual publish after approval
(TRUE, TRUE) Submit for review + auto-publish on approval
(TRUE, FALSE) ❌ Error

Phase 4 — Submit for review (if not done in Phase 3)

USE ROLE ORGADMIN;
ALTER LISTING <NAME> REVIEW;  -- no arguments

Use this when Phase 3 was PUBLISH=FALSE REVIEW=FALSE and you now want to submit. UI "Re-submit" button has extra preflight gates (Region availability, Access type, Publishing profile) that can block; SQL ALTER LISTING REVIEW bypasses UI preflight and submits directly. Review still happens.

Phase 5 — Verify state

snow sql --connection Husky --format json -q "USE ROLE ORGADMIN; DESCRIBE LISTING <NAME>;"

Confirm: state, review_state, is_limited_trial (if Trial), manifest_yaml matches submission.

Phase 6 — Update wiki state

Update the listing-state table in docs/strategy/2026-04-23-publishing-strategy.md (and any project pages that reference current marketplace state). Do not skip — wiki SSOT drift is a known operational failure mode.

Standards

✅ Must do

  • Always run Phase 0 row-count check before any submit. The 2026-04-28 incident exists because this was skipped.
  • Use snow sql -c Husky CLI, not Snowsight Worksheets UI for multi-statement scripts.
  • Use $$...$$ dollar-quotes for inline manifest YAML, never '...'.
  • Country names UPPERCASE human-readable: UNITED STATES not USA/US. HONG KONG not HK.
  • Continent names UPPERCASE space-separated: NORTH AMERICA not NORTH_AMERICA.
  • coverage.states: [] must always be present, even when empty. Otherwise: "When Geo Attributues has COUNTRIES, Coverage needs to have US states or Countries information" — note typo "Attributues" in actual error string is authoritative.
  • For Trial: limited_trial_plan: trial_time_limit: <int>. NOT trial_details: (latter doesn't flip is_limited_trial flag — empirically verified 2026-04-28 against #60 + #61).
  • USE ROLE between phases when script crosses ACCOUNTADMIN ↔ ORGADMIN boundary.
  • Stick to business_needs[].name = "Audience Activation" unless you have rollback time budgeted.
  • Documentation URL must be product-specific: huskydata.io/products/<sku>, not generic /segments. Reviewer rejects on this.

❌ Must not

  • ❌ Put real production views (V_HEM_US 910M, V_MAID_APAC_PLUS_US 33.6M) into any Free or Limited Trial share. Hard red line — see Failure Mode #1.
  • ❌ Use CREATE LISTING (no EXTERNAL) — syntax error.
  • ❌ Use CREATE OR REPLACE LISTING — unsupported. Use DROP LISTING IF EXISTS then CREATE if you need to replace.
  • ❌ Add DISTRIBUTION = EXTERNAL clause — EXTERNAL keyword in command name already sets it.
  • ❌ Try ALTER LISTING ... SET ACCESS='LIMITED_TRIAL' — only SET COMMENT is supported. Access type flips via manifest limited_trial_plan block + ALTER LISTING with new YAML.
  • ❌ Speculatively add optional YAML sections (data_dictionary, resources.media, support_contact, approver_contact) to a draft. Each unknown field = at least one rejection cycle.
  • ❌ Set targets.regions: ALL at CREATE time — fires 090857 Autofulfillment must be specified. Set single region (PUBLIC.AWS_US_WEST_2) at create, expand via UI later.
  • ❌ Mention any of: AlikeAudience / Experian / Hotmob / Acxiom / Eyeota in manifest text. (Supplier confidentiality black-list.)
  • ❌ Use markdown tables in description — UI renders pipes literally. Use bullets + **bold** headings only.
  • ❌ Use 3-part names (HUSKY_DATA.SHARE.V_HEM_US) in usage_examples.query. Consumer chooses DB name at mount time — use SHARE.V_HEM_US (2-part).

Access Type Decision Tree

Data character Access type
Reference (catalog, crosswalk, coverage rollup) FREE
Sample / pre-purchase taste (≤1M rows, deterministic hash) LIMITED_TRIAL
Real production audience data NOT on Marketplacesales@huskydata.io direct contract OR is_by_request=true (request-approval flow)
Paid pay-per-mount PAID with Stripe Express + Marketplace Ops onboarding (see Paid Listing Path)

🛑 Reviewer feedback "submit as Limited Trial" is a trap. Reviewer cares about listing-type ↔ description consistency, NOT whether real data leaks. If reviewer says flip to Trial, the right move is rebuild share with sample views, NOT flip access type while real data still attached.

Sample views — deterministic hash pattern

For Trial shares, build sample views with reproducible-but-bounded output:

-- HUSKY_DATA.SHARE.V_HEM_US_SAMPLE — ~991 rows
CREATE OR REPLACE VIEW HUSKY_DATA.SHARE.V_HEM_US_SAMPLE AS
SELECT * FROM V_HEM_US WHERE ABS(HASH(hem)) % 1000000 < 1;

-- HUSKY_DATA.SHARE.V_MAID_APAC_PLUS_US_SAMPLE — ~1051 rows
CREATE OR REPLACE VIEW HUSKY_DATA.SHARE.V_MAID_APAC_PLUS_US_SAMPLE AS
SELECT * FROM V_MAID_APAC_PLUS_US WHERE ABS(HASH(maid)) % 30000 < 1;

Same query → same rows on repeat. Built for reproducible schema/quality/coverage evaluation by buyers, not freshness. Consumer wanting fresh production → upgrade to Paid.

Output

  • Listing in state=PUBLISHED, review_state=APPROVED (or PENDING waiting on reviewer)
  • Manifest YAML committed to docs/internal/snowflake-listings/<listing>-<YYYY-MM-DD>.yaml for traceability
  • Listing-state table updated in docs/strategy/2026-04-23-publishing-strategy.md
  • This playbook's last_reviewed date bumped if any new gotcha discovered (and Failure Modes appended)

Review

Self-check (must pass before reporting done)

  • Phase 0 row-count check executed and output captured
  • DESC LISTING <name> confirms is_limited_trial matches intent
  • Manifest YAML committed to repo (not just /tmp/)
  • Wiki state table updated
  • If new error / quirk encountered: appended to § Failure Modes with date

Human sign-off gate (Benjamin must approve before)

  • First-time Paid listing submit (510404 path)
  • Any access-type flip (Free → Trial, Trial → Paid)
  • Any share content change that touches V_HEM_* or V_MAID_* real-data views
  • First-time submit of a listing whose share contains a view ≥10M rows

For routine resubmits (manifest copy edits, geo expansion, retry after reviewer feedback), the agent can self-approve and report.

Failure Modes

Each entry: pattern → root cause → fix.

#1 (CRITICAL) — Real production view in Free/Trial share

Pattern: Reviewer feedback says "flip to Limited Trial", autopilot flips Access Type without rebuilding share content. Real V_HEM_US (910M rows) or V_MAID_APAC_PLUS_US (33.6M) gets auto-mounted by trial consumers within 24hr SLA.

Why it's a red line (per owner): "一見光就人地用左唔會買。佢可以開好多 account 得閒拎我地 data". Marketplace trial = zero-friction self-serve mount = data permanently leaked.

Fix (executed 2026-04-28):

USE ROLE ACCOUNTADMIN;
REVOKE SELECT ON VIEW HUSKY_DATA.SHARE.V_HEM_US FROM SHARE HUSKY_MOBILE_TRIAL_US;
REVOKE SELECT ON VIEW HUSKY_DATA.SHARE.V_MAID_APAC_PLUS_US FROM SHARE HUSKY_MOBILE_TRIAL_CROSSBORDER;
-- ...regrant only sample views
GRANT SELECT ON VIEW HUSKY_DATA.SHARE.V_HEM_US_SAMPLE TO SHARE HUSKY_MOBILE_TRIAL_US;

#2 — 510404 Account not supported for Marketplace Purchases

Pattern: CREATE EXTERNAL LISTING ... FROM '@stage/<paid_folder>' (manifest contains pricing_plans) returns:

510404 (22000): Account not supported for Marketplace Purchases.
Please contact support to resolve this issue.

Root cause: account billing/service address is HK (legacy snapshot), Marketplace Purchases eligible-country list excludes HK. Husky entity is SG-incorporated. Same root cause as AWS Marketplace seller appeal — both external marketplaces have HK on file from old account creation.

Fix order: 1. Update Snowsight Admin > Billing > Service+Billing address from HK → SG (151 Chin Swee Road, #07-12 Manhattan House, Singapore 169876) 2. Wait 24-72hr for propagation 3. Re-test via CREATE EXTERNAL LISTING ... FROM '@stage' with pricing_plans block 4. Only if still gated, file Marketplace Ops case explicitly citing the address update

Eligible countries: AU, CA, CO, FI, FR, DE, IE, IL, IT, JP, KSA, MX, NL, NZ, NO, SG, SE, CH, UK, US.

#3 — 090857 Autofulfillment must be specified

Pattern: CREATE EXTERNAL LISTING ... AS $$ targets: regions: ALL $$ errors.

Root cause: Multi-region requires CROSS_CLOUD_AUTO_FULFILLMENT_ENABLEMENT privilege not granted by default.

Fix: Set single region at create (targets: regions: ["PUBLIC.AWS_US_WEST_2"]), expand via UI Provider Studio > Region Availability after listing exists.

#4 — Subtitle must be under 110 chars

Pattern: Manifest validation rejects subtitle.

Root cause: hard cap 110 chars, Unicode counts, em-dashes count.

Fix: trim. Common pattern: drop redundant qualifier ("APAC" / "Mobile") since it appears in title.

#5 — Schema traps table

Trap Symptom Fix
CREATE LISTING (no EXTERNAL) syntax error Use CREATE EXTERNAL LISTING
CREATE OR REPLACE EXTERNAL LISTING unsupported DROP LISTING IF EXISTS then CREATE
DISTRIBUTION = EXTERNAL clause redundant — EXTERNAL keyword in command sets it Remove the clause
(PUBLISH, REVIEW) = (TRUE, FALSE) "publish needs to be FALSE when requesting a listing to not be reviewed" Use linked-boolean combos: (F,F) / (F,T) / (T,T) only
ALTER LISTING SET ACCESS='...' only SET COMMENT supported Flip access via ALTER LISTING <n> AS $$<yaml with limited_trial_plan>$$ PUBLISH=TRUE REVIEW=TRUE
trial_details: block doesn't flip is_limited_trial flag Use limited_trial_plan: { trial_time_limit: <int> }
access: / access_type: in manifest "Unrecognized field access" Access not a manifest field at top level — see limited_trial_plan for Trial, pricing_plans for Paid
regions: in manifest top-level "Unrecognized field regions" Regions set via targets: block or UI Region Availability
Markdown tables in description UI renders \| pipes \| raw \| literally Use bullet lists + **bold** headings
data_dictionary.featured as array "Cannot deserialize from Array" Use single object {database, objects}, not list. Or omit entirely.
data_dictionary.objects[].type: VIEW "Unrecognized field type" Omit type — Snowflake infers
resources.media non-YouTube URL "Not a valid media link" Only YouTube. Omit if no video.
support_contact / approver_contact "not allowed in external listings" Remove — these come from provider profile for public Marketplace
categories: ["ADVERTISING_AND_MARKETING"] "Invalid category" Enum: MARKETING / IDENTITY / ANALYTICS TOOLS / CORTEX AI READY. Reject message lists full set.
business_needs[].name = "Audience Sizing" etc "not in standard business needs" Only "Audience Activation" confirmed working
3-part names in usage_examples.query "Database names cannot appear" SHARE.V_MAID not HUSKY_DATA.SHARE.V_MAID
data_attributes missing geography AND time "Geo or Time attributes required" Include at least one. geography: { geo_option: NOT_APPLICABLE } is escape hatch
data_attributes.time.time_range: "MONTHLY" (string) internal error (expects object) Avoid time_range; use geo_option: NOT_APPLICABLE instead
coverage missing states: [] with geo_option: COUNTRIES "When Geo Attributues has COUNTRIES…" (typo authoritative) Add coverage: { states: [], continents: {...} }
documentation URL = /segments reviewer rejects "not product-specific" Use huskydata.io/products/<sku>

#6 — Provider profile literal \n rendering

Pattern: Provider profile description shows literal \n strings instead of newlines on Marketplace public page.

Root cause: profile UI doesn't interpret escape sequences in some fields.

Fix: re-submit profile with actual newlines (paste directly, don't escape).

Pattern: profile rejected on privacyUrl.

Root cause: Snowflake requires dedicated privacy page (must render personal-data / GDPR / CCPA / data-subject-rights / retention / opt-out keywords), not a generic compliance landing page.

Fix: point privacyUrl to https://huskydata.io/company/privacy (dedicated page) → re-submit profile via UI Update Profile.

Paid listings have an additional gate (Failure Mode #2) and require Stripe Express setup:

  1. Verify account address = SG (Admin > Billing > Service+Billing). HK address blocks at 510404.
  2. File Marketplace Operations case via provider-onboarding-case form requesting "Enable Marketplace Purchases on account ciqcvik-ujb07324".
  3. Stripe Express setup: Snowsight Admin > Billing > Marketplace billing → register with Husky Technology Pte Ltd details + MFA. (Tab is invisible until step 2 completes.)
  4. Wait Snowflake Partner Manager engagement + commercial review.
  5. Stripe payout method "Completed & verified" — 3-14 working days typical.
  6. Pre-stage manifest + pricing plan files:
    @HUSKY_DATA.PUBLIC.LISTING_MANIFESTS/
      hem_bundle/
        manifest.yml
        pricing_plan_monthly.yaml
    
  7. CREATE EXTERNAL LISTING via stage path:
    USE ROLE ORGADMIN;
    CREATE EXTERNAL LISTING HUSKY_USA_MOBILE_HEM_BUNDLE
      SHARE HUSKY_USA_MOBILE_HEM_BUNDLE
      FROM '@HUSKY_DATA.PUBLIC.LISTING_MANIFESTS/hem_bundle';
    

Pricing plan YAML (FLAT_FEE):

display_name: "..."
currency: USD
pricing_model: FLAT_FEE
base_fee: 20000.0
billing_duration_months: 1
sales_motion: SELF_SERVE
metadata:
  description: "..."
  price: "$20,000 / month"
  button_text: "Subscribe"
  value_propositions: ["...", "..."]
  visibility: VISIBLE
  state: PUBLISHED

Manifest references plan via:

pricing_plans:
- name: PLAN_NAME_UPPERCASE
  type: FILE
  path: pricing_plan_monthly.yaml   # relative to manifest folder

Pre-staging is safe before enablement: stage upload + share grants can all be ready. Listing creation will 510404 until step 2-5 complete; one CREATE statement away from live afterwards.

Profile lifecycle

UNSENT (draft_status)
  └─► PENDING (ALTER PROFILE SET METADATA = '...' then submit via UI)
        ├─► APPROVED (live — listings can publish)
        └─► REJECTED — reject reason in `rejected_reason` JSON column
              └─► ALTER PROFILE SET METADATA = '...' + submit via UI Update Profile flow → PENDING again

Profile metadata update via SQL:

USE ROLE ORGADMIN;
ALTER PROFILE "<NAME>" SET METADATA = $$<full JSON metadata>$$;

Extract current metadata first via SHOW PROFILES IN DATA EXCHANGE SNOWFLAKE_DATA_MARKETPLACE, patch the field (e.g. privacyUrl), write back. UI re-submit still required — there is NO SQL ALTER PROFILE SUBMIT equivalent.

Listing lifecycle

DRAFT/UNSENT
  └─► DRAFT/PENDING        (ALTER LISTING ... REVIEW)
        ├─► APPROVED → PUBLISHED   (ALTER LISTING ... PUBLISH)
        └─► DRAFT/REJECTED — reason in rejection_reason column
              └─► ALTER LISTING ... AS $$ ... $$ REVIEW

Known listing reject reasons: - LISTING_PRACTICES_LISTING_TYPE: Free listings should expose full production datasets. If your share has samples, flip to Limited Trial WITH limited_trial_plan in manifest AND ensure share contents match (Failure Mode #1). - Free-with-trial-data: description implies trial-like behavior on a Free listing → either rewrite description OR flip to Limited Trial properly.

Role-switching gotcha

The Husky Snowflake account defaults to ACCOUNTADMIN. Every listing UI interaction requires switching to ORGADMIN via Account Menu → Switch Role. If left on ACCOUNTADMIN, "Edit" / "Submit" buttons are disabled with misleading "no permission" messages, masking real state.

CLI sessions: USE ROLE ORGADMIN at top of each script (or before each phase that needs it).

References

  • docs/internal/snowflake-phase2-listings-2026-04-24.sql — last known-good CREATE LISTING template
  • docs/internal/dump_listing_manifest.sh — canonical manifest extractor
  • docs/internal/snowflake-resubmit-2026-04-28.sql — Trial flip + sample-view rebuild script
  • docs/reference/snowflake-naming-convention.mdHUSKY_<GEO>_<CHANNEL>_<TIER> pattern
  • docs/strategy/2026-04-23-publishing-strategy.md — current listing-state table (revised 2026-04-28)
  • Snowflake docs: listing-manifest-reference (WebFetch-able)
  • Provider eligibility: provider-becoming docs
  • Marketplace Ops: provider-onboarding-case form

Changelog

  • 2026-04-29 — v2 rewrite. Integrated post-2026-04-23 learnings: corrected DDL to CREATE EXTERNAL LISTING (was CREATE LISTING), removed obsolete DISTRIBUTION = EXTERNAL clause, replaced trial_details with limited_trial_plan: trial_time_limit: (verified 2026-04-28 against #60 + #61), added Failure Mode #1 (real-data-leak incident), Failure Mode #2 (510404 monetization gate + SG address fix), sample-view deterministic hash pattern, expanded geography schema with coverage.states: [] requirement. Skill .claude/skills/snowflake-listing-submit/ now points here as SSOT.
  • 2026-04-23 — v1 initial draft. 14+ rejection cycles documented; schema traps table; profile + listing lifecycle diagrams; role-switching gotcha. Captured during sprint 2026-04-20→23.