@takuhon/core 0.16.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  var $schema = "https://json-schema.org/draft/2020-12/schema";
2
- var $id = "https://takuhon.example/schemas/0.5.0/takuhon.schema.json";
2
+ var $id = "https://takuhon.example/schemas/0.6.0/takuhon.schema.json";
3
3
  var title = "Takuhon Profile";
4
4
  var description = "Portable profile data format consumed by @takuhon/core. The canonical contract for profile content authored as takuhon.json.";
5
5
  var type = "object";
@@ -545,6 +545,80 @@ var $defs = {
545
545
  },
546
546
  activity: {
547
547
  $ref: "#/$defs/ActivitySettings"
548
+ },
549
+ publicVisibility: {
550
+ $ref: "#/$defs/PublicVisibility"
551
+ }
552
+ }
553
+ },
554
+ PublicVisibility: {
555
+ type: "object",
556
+ additionalProperties: false,
557
+ description: "Per-section public visibility (added in 0.6.0). Each key is a content section; setting it to false hides that whole section from every public surface (GET /, /api/profile, /api/jsonld, /takuhon.json, MCP, and the derived CV) via the shared applyPublicPrivacyFilter. An absent key — or an absent object — means the section is public, so the default is all-visible and omitting this block is fully backwards-compatible. The profile identity (profile.displayName, …) is always public and is intentionally not a key here. Field-level controls (contact.showEmail, meta.privacy.*) still apply within a visible section: visibility is the AND of the feature toggle, this section flag, and the field flag.",
558
+ properties: {
559
+ links: {
560
+ type: "boolean",
561
+ description: "Default true. When false, links[] is emitted empty on public surfaces."
562
+ },
563
+ careers: {
564
+ type: "boolean",
565
+ description: "Default true. When false, careers[] is emitted empty on public surfaces."
566
+ },
567
+ projects: {
568
+ type: "boolean",
569
+ description: "Default true. When false, projects[] is emitted empty on public surfaces."
570
+ },
571
+ skills: {
572
+ type: "boolean",
573
+ description: "Default true. When false, skills[] is emitted empty on public surfaces."
574
+ },
575
+ certifications: {
576
+ type: "boolean",
577
+ description: "Default true. When false, certifications[] is emitted empty on public surfaces."
578
+ },
579
+ memberships: {
580
+ type: "boolean",
581
+ description: "Default true. When false, memberships[] is emitted empty on public surfaces."
582
+ },
583
+ volunteering: {
584
+ type: "boolean",
585
+ description: "Default true. When false, volunteering[] is emitted empty on public surfaces."
586
+ },
587
+ honors: {
588
+ type: "boolean",
589
+ description: "Default true. When false, honors[] is emitted empty on public surfaces."
590
+ },
591
+ education: {
592
+ type: "boolean",
593
+ description: "Default true. When false, education[] is emitted empty on public surfaces."
594
+ },
595
+ publications: {
596
+ type: "boolean",
597
+ description: "Default true. When false, publications[] is emitted empty on public surfaces."
598
+ },
599
+ languages: {
600
+ type: "boolean",
601
+ description: "Default true. When false, languages[] is emitted empty on public surfaces."
602
+ },
603
+ courses: {
604
+ type: "boolean",
605
+ description: "Default true. When false, courses[] is emitted empty on public surfaces."
606
+ },
607
+ patents: {
608
+ type: "boolean",
609
+ description: "Default true. When false, patents[] is emitted empty on public surfaces."
610
+ },
611
+ testScores: {
612
+ type: "boolean",
613
+ description: "Default true. When false, testScores[] is emitted empty on public surfaces."
614
+ },
615
+ recommendations: {
616
+ type: "boolean",
617
+ description: "Default true. When false, recommendations[] is emitted empty on public surfaces."
618
+ },
619
+ contact: {
620
+ type: "boolean",
621
+ description: "Default true. When false, the contact section (email, formUrl) is emitted empty on public surfaces."
548
622
  }
549
623
  }
550
624
  },
@@ -1735,6 +1809,80 @@ declare const schema: {
1735
1809
  activity: {
1736
1810
  $ref: string;
1737
1811
  };
1812
+ publicVisibility: {
1813
+ $ref: string;
1814
+ };
1815
+ };
1816
+ };
1817
+ PublicVisibility: {
1818
+ type: string;
1819
+ additionalProperties: boolean;
1820
+ description: string;
1821
+ properties: {
1822
+ links: {
1823
+ type: string;
1824
+ description: string;
1825
+ };
1826
+ careers: {
1827
+ type: string;
1828
+ description: string;
1829
+ };
1830
+ projects: {
1831
+ type: string;
1832
+ description: string;
1833
+ };
1834
+ skills: {
1835
+ type: string;
1836
+ description: string;
1837
+ };
1838
+ certifications: {
1839
+ type: string;
1840
+ description: string;
1841
+ };
1842
+ memberships: {
1843
+ type: string;
1844
+ description: string;
1845
+ };
1846
+ volunteering: {
1847
+ type: string;
1848
+ description: string;
1849
+ };
1850
+ honors: {
1851
+ type: string;
1852
+ description: string;
1853
+ };
1854
+ education: {
1855
+ type: string;
1856
+ description: string;
1857
+ };
1858
+ publications: {
1859
+ type: string;
1860
+ description: string;
1861
+ };
1862
+ languages: {
1863
+ type: string;
1864
+ description: string;
1865
+ };
1866
+ courses: {
1867
+ type: string;
1868
+ description: string;
1869
+ };
1870
+ patents: {
1871
+ type: string;
1872
+ description: string;
1873
+ };
1874
+ testScores: {
1875
+ type: string;
1876
+ description: string;
1877
+ };
1878
+ recommendations: {
1879
+ type: string;
1880
+ description: string;
1881
+ };
1882
+ contact: {
1883
+ type: string;
1884
+ description: string;
1885
+ };
1738
1886
  };
1739
1887
  };
1740
1888
  ActivitySettings: {
@@ -2649,6 +2797,42 @@ interface Settings {
2649
2797
  enableAnalytics?: boolean;
2650
2798
  /** Opt-in developer-activity dashboard configuration (added in 0.5.0). */
2651
2799
  activity?: ActivitySettings;
2800
+ /** Per-section public visibility (added in 0.6.0). Absent = all sections visible. */
2801
+ publicVisibility?: PublicVisibility;
2802
+ }
2803
+ /**
2804
+ * Per-section public/private visibility (added in 0.6.0).
2805
+ *
2806
+ * Each key names a content section. Setting it to `false` hides that whole
2807
+ * section from every public surface (`GET /`, `/api/profile`, `/api/jsonld`,
2808
+ * `/takuhon.json`, MCP, and the derived CV) through the shared
2809
+ * {@link applyPublicPrivacyFilter}. An absent key — or an absent object —
2810
+ * means the section is public, so the default is all-visible and omitting this
2811
+ * block is fully backwards-compatible.
2812
+ *
2813
+ * The profile identity (`profile.displayName`, …) is always public and is
2814
+ * intentionally not representable here. Field-level controls
2815
+ * (`contact.showEmail`, `meta.privacy.*`) still apply within a visible section:
2816
+ * a field is public only when the feature toggle, this section flag, and the
2817
+ * field flag all allow it (AND composition).
2818
+ */
2819
+ interface PublicVisibility {
2820
+ links?: boolean;
2821
+ careers?: boolean;
2822
+ projects?: boolean;
2823
+ skills?: boolean;
2824
+ certifications?: boolean;
2825
+ memberships?: boolean;
2826
+ volunteering?: boolean;
2827
+ honors?: boolean;
2828
+ education?: boolean;
2829
+ publications?: boolean;
2830
+ languages?: boolean;
2831
+ courses?: boolean;
2832
+ patents?: boolean;
2833
+ testScores?: boolean;
2834
+ recommendations?: boolean;
2835
+ contact?: boolean;
2652
2836
  }
2653
2837
  /**
2654
2838
  * Owner-curated configuration for the developer-activity dashboard (GitHub /
@@ -3020,7 +3204,7 @@ interface LocalizedTakuhon {
3020
3204
  * versions whose JSON Schema this package literally bundles, not the full
3021
3205
  * support window seen by end users.
3022
3206
  */
3023
- declare const SUPPORTED_SCHEMA_VERSIONS: readonly ["0.1.0", "0.2.0", "0.3.0", "0.4.0", "0.5.0"];
3207
+ declare const SUPPORTED_SCHEMA_VERSIONS: readonly ["0.1.0", "0.2.0", "0.3.0", "0.4.0", "0.5.0", "0.6.0"];
3024
3208
  /**
3025
3209
  * A single validation failure.
3026
3210
  *
@@ -3270,20 +3454,32 @@ declare function importTakuhon(data: ExportedTakuhon): Takuhon;
3270
3454
  /**
3271
3455
  * Public-endpoint privacy filter for takuhon profile documents.
3272
3456
  *
3273
- * Strips fields that the spec's privacy posture marks as opt-in for public
3457
+ * Strips content that the spec's privacy posture marks as opt-in for public
3274
3458
  * exposure, before the document reaches a public reader (a public API
3275
- * response, a statically built page, …). The filter is deliberately
3276
- * conservative: when `meta.privacy` is absent the most restrictive
3277
- * interpretation applies (everything sensitive is hidden), and the operator
3278
- * must explicitly opt into disclosure by setting the relevant flag to
3279
- * `false`.
3459
+ * response, a server-rendered page, a statically built page, …). Two layers
3460
+ * compose here, both conservative by default:
3461
+ *
3462
+ * 1. **Section layer** (`settings.publicVisibility`, schema 0.6.0). Each
3463
+ * content section the owner sets to `false` is emptied: array sections
3464
+ * become `[]` and the `contact` section becomes `{}`. An absent key — or an
3465
+ * absent `publicVisibility` block — means the section is public, so the
3466
+ * default is all-visible and older documents are unaffected.
3467
+ * 2. **Field layer** (`meta.privacy.*`, `contact.showEmail`). Within a visible
3468
+ * section, individual identifying fields are stripped unless the operator
3469
+ * opts into disclosure.
3470
+ *
3471
+ * Visibility is the AND of the two layers (the surface-level `enable*` feature
3472
+ * toggles are a third, orthogonal layer enforced by the route / renderer, not
3473
+ * here): a field survives only when its section is visible *and* its field
3474
+ * flag allows it. Hiding a whole section short-circuits its field checks.
3280
3475
  *
3281
3476
  * This lives in `@takuhon/core` because it is a pure transform over the core
3282
3477
  * document types with no transport coupling, so every public surface — the
3283
- * API layer, the CLI's `build`, future renderers — applies the exact same
3478
+ * API layer (`GET /`, `/api/profile`, `/api/jsonld`, `/takuhon.json`), the
3479
+ * CLI's `build`, the MCP executor, the derived CV — applies the exact same
3284
3480
  * projection. `@takuhon/api` re-exports it for backwards compatibility.
3285
3481
  *
3286
- * Fields filtered:
3482
+ * Field-layer fields filtered:
3287
3483
  *
3288
3484
  * - `certifications[*].credentialId` — hidden when
3289
3485
  * `meta.privacy.hideCredentialIds !== false` (default true).
@@ -3295,12 +3491,16 @@ declare function importTakuhon(data: ExportedTakuhon): Takuhon;
3295
3491
  * records (issued patents are published by the granting office) and Spec
3296
3492
  * §6.21 explicitly excludes them from the privacy block.
3297
3493
  *
3494
+ * The `profile` identity (`profile.displayName`, …) is always public and is
3495
+ * not a `publicVisibility` key, so it is never emptied here.
3496
+ *
3298
3497
  * Behavior:
3299
3498
  *
3300
3499
  * - Pure function. The input is never mutated; a shallow-copied result is
3301
3500
  * returned with only the touched arrays / objects replaced.
3302
- * - When no filter applies (every flag opts into disclosure), the original
3303
- * reference is returned as-is so callers can compare by identity.
3501
+ * - When no filter applies (every section visible and every field opts into
3502
+ * disclosure), the original reference is returned as-is so callers can
3503
+ * compare by identity.
3304
3504
  * - Admin endpoints (`/api/admin/*`, including `/api/admin/export`) MUST NOT
3305
3505
  * call this helper — they always serve the full document to authenticated
3306
3506
  * callers.
@@ -3308,8 +3508,7 @@ declare function importTakuhon(data: ExportedTakuhon): Takuhon;
3308
3508
 
3309
3509
  /**
3310
3510
  * Union of the two profile shapes that traverse the public path. The fields
3311
- * the filter touches (`certifications[*].credentialId`, `education[*].grade`,
3312
- * `contact.email`) are structurally identical between {@link Takuhon} and
3511
+ * the filter touches are structurally identical between {@link Takuhon} and
3313
3512
  * {@link LocalizedTakuhon}, so the same logic applies to either shape.
3314
3513
  */
3315
3514
  type FilterableProfile = Takuhon | LocalizedTakuhon;
@@ -4092,6 +4291,6 @@ declare function stripImageMetadata(bytes: Uint8Array, mime: AcceptedImageMime):
4092
4291
  * A takuhon profile document's `schemaVersion` field must be migrate-compatible
4093
4292
  * with this version. See operational-lifecycle docs for the migration policy.
4094
4293
  */
4095
- declare const SCHEMA_VERSION = "0.5.0";
4294
+ declare const SCHEMA_VERSION = "0.6.0";
4096
4295
 
4097
- export { ACCEPTED_IMAGE_MIME_TYPES, type AcceptedImageMime, type ActivitySettings, type ActivitySnapshot, type ActivityStorage, type Address, type AssetOptions, type AssetRecord, type Avatar, type Career, type Certification, type CodingTime, ConflictError, type Contact, type ContentLicense, type ContentLicenseAttribution, type ContributionCalendar, type ContributionDay, type Course, type CvDocument, type CvHeader, type CvSection, type CvSectionKind, DARK_PALETTE, type Education, type ExportOptions, type ExportedTakuhon, type GravatarOptions, type Honor, IMAGE_EXTENSIONS, type ImageInfo, ImportError, type Iso3166Alpha2, type IsoDateTime, LIGHT_PALETTE, type Language, type LanguageBreakdown, type LanguageProficiency, type Link, type LinkBuiltin, type LinkCustom, type LinkType, type LocaleTag, type LocalizedAddress, type LocalizedAvatar, type LocalizedBody, type LocalizedCareer, type LocalizedCertification, type LocalizedCourse, type LocalizedEducation, type LocalizedHonor, type LocalizedLanguage, type LocalizedLink, type LocalizedLinkBuiltin, type LocalizedLinkCustom, type LocalizedMembership, type LocalizedPatent, type LocalizedProfile, type LocalizedProject, type LocalizedPublication, type LocalizedRecommendation, type LocalizedRecommendationAuthor, type LocalizedTakuhon, type LocalizedTestScore, type LocalizedTitle, type LocalizedVolunteering, MAX_IMAGE_BYTES, MAX_IMAGE_DIMENSION, MAX_IMAGE_FRAMES, MCP_PROFILE_SECTIONS, MCP_RESOURCES, MCP_TOOLS, type McpInputSchema, type McpProfileSection, McpRequestError, type McpResourceDefinition, type McpResourceResult, type McpToolDefinition, type McpToolResult, type Membership, type Meta, type MetaPrivacy, type Migration, MigrationError, type NormalizedTakuhon, NotFoundError, type Palette, type Patent, type PatentStatus, type Profile, type Project, type Publication, RANK_FULL_CODING_HOURS, RANK_FULL_CONTRIBUTIONS, RANK_TIER_THRESHOLDS, type RankInput, type RankTier, type RankTierLabel, type Recommendation, type RecommendationAuthor, type RenderActivitySvgOptions, SCHEMA_VERSION, SUPPORTED_SCHEMA_VERSIONS, type Schema, type Settings, type Skill, type Slug, StorageError, type Takuhon, type TakuhonAssetStorage, type TakuhonStorage, type TestScore, type ValidationError, type ValidationResult, type Volunteering, type YearMonth, applyPublicPrivacyFilter, computeLanguagePercentages, deriveCv, deriveRankTier, detectImageMime, executeMcpTool, exportTakuhon, formatCodingTime, generateJsonLd, generatePersonJsonLd, generateProfilePageJsonLd, gravatarUrl, importTakuhon, isActivitySnapshot, migrateTakuhon, migrations, normalize, readImageInfo, readMcpResource, renderActivitySvg, resolveLocale, schema, stripImageMetadata, validate };
4296
+ export { ACCEPTED_IMAGE_MIME_TYPES, type AcceptedImageMime, type ActivitySettings, type ActivitySnapshot, type ActivityStorage, type Address, type AssetOptions, type AssetRecord, type Avatar, type Career, type Certification, type CodingTime, ConflictError, type Contact, type ContentLicense, type ContentLicenseAttribution, type ContributionCalendar, type ContributionDay, type Course, type CvDocument, type CvHeader, type CvSection, type CvSectionKind, DARK_PALETTE, type Education, type ExportOptions, type ExportedTakuhon, type GravatarOptions, type Honor, IMAGE_EXTENSIONS, type ImageInfo, ImportError, type Iso3166Alpha2, type IsoDateTime, LIGHT_PALETTE, type Language, type LanguageBreakdown, type LanguageProficiency, type Link, type LinkBuiltin, type LinkCustom, type LinkType, type LocaleTag, type LocalizedAddress, type LocalizedAvatar, type LocalizedBody, type LocalizedCareer, type LocalizedCertification, type LocalizedCourse, type LocalizedEducation, type LocalizedHonor, type LocalizedLanguage, type LocalizedLink, type LocalizedLinkBuiltin, type LocalizedLinkCustom, type LocalizedMembership, type LocalizedPatent, type LocalizedProfile, type LocalizedProject, type LocalizedPublication, type LocalizedRecommendation, type LocalizedRecommendationAuthor, type LocalizedTakuhon, type LocalizedTestScore, type LocalizedTitle, type LocalizedVolunteering, MAX_IMAGE_BYTES, MAX_IMAGE_DIMENSION, MAX_IMAGE_FRAMES, MCP_PROFILE_SECTIONS, MCP_RESOURCES, MCP_TOOLS, type McpInputSchema, type McpProfileSection, McpRequestError, type McpResourceDefinition, type McpResourceResult, type McpToolDefinition, type McpToolResult, type Membership, type Meta, type MetaPrivacy, type Migration, MigrationError, type NormalizedTakuhon, NotFoundError, type Palette, type Patent, type PatentStatus, type Profile, type Project, type PublicVisibility, type Publication, RANK_FULL_CODING_HOURS, RANK_FULL_CONTRIBUTIONS, RANK_TIER_THRESHOLDS, type RankInput, type RankTier, type RankTierLabel, type Recommendation, type RecommendationAuthor, type RenderActivitySvgOptions, SCHEMA_VERSION, SUPPORTED_SCHEMA_VERSIONS, type Schema, type Settings, type Skill, type Slug, StorageError, type Takuhon, type TakuhonAssetStorage, type TakuhonStorage, type TestScore, type ValidationError, type ValidationResult, type Volunteering, type YearMonth, applyPublicPrivacyFilter, computeLanguagePercentages, deriveCv, deriveRankTier, detectImageMime, executeMcpTool, exportTakuhon, formatCodingTime, generateJsonLd, generatePersonJsonLd, generateProfilePageJsonLd, gravatarUrl, importTakuhon, isActivitySnapshot, migrateTakuhon, migrations, normalize, readImageInfo, readMcpResource, renderActivitySvg, resolveLocale, schema, stripImageMetadata, validate };