checkin

package
v0.3.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 10, 2026 License: MIT Imports: 2 Imported by: 0

Documentation

Overview

Package checkin holds the MDM check-in messages generated from Apple's device management schema: 9 schema files and 14 types.

Design

Apple publishes the wire format of the MDM check-in messages as YAML in https://github.com/apple/device-management, pinned here as a git submodule. Generating this package from that pinned commit derives the wire types, validation, and support metadata from Apple's schema (decision record 0003). Every type carries plist and json struct tags with Apple's wire keys, a Validate method driven by the schema's constraints, and support metadata queryable through Support(path) or the schema/support package.

Edit the generator to change this package. admgen verify fails when regeneration would change it or drop an exported name (schema/EXPORTED_IDENTIFIERS.lock). Protocol semantics that Apple documents only in prose live in the hand-written packages that import this one.

References

Index

Constants

View Source
const (
	// MessageTypeAuthenticate: Authenticate
	MessageTypeAuthenticate = "Authenticate"
	// MessageTypeCheckOut: Check Out
	MessageTypeCheckOut = "CheckOut"
	// MessageTypeDeclarativeManagement: Declarative Management
	MessageTypeDeclarativeManagement = "DeclarativeManagement"
	// MessageTypeGetBootstrapToken: Get Bootstrap Token
	MessageTypeGetBootstrapToken = "GetBootstrapToken" // #nosec G101 -- Apple wire identifier, not a credential
	// MessageTypeGetToken: Get Token
	MessageTypeGetToken = "GetToken" // #nosec G101 -- Apple wire identifier, not a credential
	// MessageTypeReturnToService: Return To Service
	MessageTypeReturnToService = "ReturnToService"
	// MessageTypeSetBootstrapToken: Set Bootstrap Token
	MessageTypeSetBootstrapToken = "SetBootstrapToken" // #nosec G101 -- Apple wire identifier, not a credential
	// MessageTypeTokenUpdate: Token Update
	MessageTypeTokenUpdate = "TokenUpdate" // #nosec G101 -- Apple wire identifier, not a credential
	// MessageTypeUserAuthenticate: User Authenticate
	MessageTypeUserAuthenticate = "UserAuthenticate"
)

Wire identifiers.

Variables

View Source
var Registry = map[string]Entry{
	"Authenticate":          {ID: "Authenticate", Schema: "mdm/checkin/authenticate.yaml", Title: "Authenticate", New: func() Message { return new(Authenticate) }},
	"CheckOut":              {ID: "CheckOut", Schema: "mdm/checkin/checkout.yaml", Title: "Check Out", New: func() Message { return new(CheckOut) }},
	"DeclarativeManagement": {ID: "DeclarativeManagement", Schema: "mdm/checkin/declarativemanagement.yaml", Title: "Declarative Management", New: func() Message { return new(DeclarativeManagement) }},
	"GetBootstrapToken":     {ID: "GetBootstrapToken", Schema: "mdm/checkin/getbootstraptoken.yaml", Title: "Get Bootstrap Token", New: func() Message { return new(GetBootstrapToken) }, NewResponse: func() any { return new(GetBootstrapTokenResponse) }},
	"GetToken":              {ID: "GetToken", Schema: "mdm/checkin/gettoken.yaml", Title: "Get Token", New: func() Message { return new(GetToken) }, NewResponse: func() any { return new(GetTokenResponse) }},
	"ReturnToService":       {ID: "ReturnToService", Schema: "mdm/checkin/returntoservice.yaml", Title: "Return To Service", New: func() Message { return new(ReturnToService) }, NewResponse: func() any { return new(ReturnToServiceResponse) }},
	"SetBootstrapToken":     {ID: "SetBootstrapToken", Schema: "mdm/checkin/setbootstraptoken.yaml", Title: "Set Bootstrap Token", New: func() Message { return new(SetBootstrapToken) }},
	"TokenUpdate":           {ID: "TokenUpdate", Schema: "mdm/checkin/tokenupdate.yaml", Title: "Token Update", New: func() Message { return new(TokenUpdate) }},
	"UserAuthenticate":      {ID: "UserAuthenticate", Schema: "mdm/checkin/userauthenticate.yaml", Title: "User Authenticate", New: func() Message { return new(UserAuthenticate) }},
}

Registry maps Go type names to constructors, one entry per schema file. Several schemas may share a wire identifier (for example six profile payloads use com.apple.MCX), so look up by identifier with ByID.

Functions

func IDs

func IDs() []string

IDs returns the distinct wire identifiers in sorted order.

func Support

func Support(path string) *support.Entry

Support returns the support entry for a key path such as "DeviceLock.Message" or "DeviceLock.response.MessageResult", or nil when unknown.

Types

type Authenticate

type Authenticate struct {
	// The device's name.
	DeviceName string `plist:"DeviceName" json:"DeviceName"`
	// The device's model name.
	ModelName string `plist:"ModelName" json:"ModelName"`
	// The device's model.
	Model string `plist:"Model" json:"Model"`
	// The message type, which requires a value of `Authenticate`.
	MessageType string `plist:"MessageType" json:"MessageType"`
	// The topic that the device subscribes to.
	Topic string `plist:"Topic" json:"Topic"`
	// The device's UDID (unique device identifier). The system requires this value if the
	// enrollment type is a device enrollment.
	UDID *string `plist:"UDID,omitempty" json:"UDID,omitempty"`
	// The per-enrollment identifier for the device. The system requires this value if the
	// enrollment type is a user enrollment.
	EnrollmentID *string `plist:"EnrollmentID,omitempty" json:"EnrollmentID,omitempty"`
	// The device's OS version.
	OSVersion *string `plist:"OSVersion,omitempty" json:"OSVersion,omitempty"`
	// The device's build version.
	BuildVersion *string `plist:"BuildVersion,omitempty" json:"BuildVersion,omitempty"`
	// The device's product name (such as `iPhone17,2`).
	ProductName *string `plist:"ProductName,omitempty" json:"ProductName,omitempty"`
	// The device's serial number.
	SerialNumber *string `plist:"SerialNumber,omitempty" json:"SerialNumber,omitempty"`
	// The device's IMEI (International Mobile Equipment Identity).
	IMEI *string `plist:"IMEI,omitempty" json:"IMEI,omitempty"`
	// The device's MEID (Mobile Equipment Identifier).
	MEID *string `plist:"MEID,omitempty" json:"MEID,omitempty"`
}

Authenticate: Authenticates a user during MDM payload installation.

Authenticate corresponds to mdm/checkin/authenticate.yaml (Authenticate).

func (*Authenticate) MessageTypeName

func (*Authenticate) MessageTypeName() string

MessageTypeName returns "Authenticate".

func (*Authenticate) SchemaPath

func (*Authenticate) SchemaPath() string

SchemaPath returns the Apple schema file this type was generated from.

func (*Authenticate) Validate

func (x *Authenticate) Validate(t support.Target) error

Validate checks x against the schema. With a non-zero target it also checks that every present key is supported on that OS version and enrollment context.

type CheckOut

type CheckOut struct {
	// The message type, which requires a value of `CheckOut`.
	MessageType string `plist:"MessageType" json:"MessageType"`
	// The topic the device subscribes to.
	Topic string `plist:"Topic" json:"Topic"`
	// The device's UDID (unique device identifier). The system requires this value if the
	// enrollment type is a device enrollment.
	UDID string `plist:"UDID" json:"UDID"`
	// The per-enrollment identifier for the device. The system requires this value if the
	// enrollment type is a user enrollment.
	EnrollmentID string `plist:"EnrollmentID" json:"EnrollmentID"`
}

CheckOut: Responds to the removal of the MDM enrollment profile from a device.

CheckOut corresponds to mdm/checkin/checkout.yaml (Check Out).

func (*CheckOut) MessageTypeName

func (*CheckOut) MessageTypeName() string

MessageTypeName returns "CheckOut".

func (*CheckOut) SchemaPath

func (*CheckOut) SchemaPath() string

SchemaPath returns the Apple schema file this type was generated from.

func (*CheckOut) Validate

func (x *CheckOut) Validate(t support.Target) error

Validate checks x against the schema. With a non-zero target it also checks that every present key is supported on that OS version and enrollment context.

type DeclarativeManagement

type DeclarativeManagement struct {
	// The message type, which requires a value of `DeclarativeManagement`.
	MessageType string `plist:"MessageType" json:"MessageType"`
	// The type of operation the declaration is requesting. This key needs to be one of these
	// values:
	Endpoint string `plist:"Endpoint" json:"Endpoint"`
	// A Base64-encoded JSON object using the `SynchronizationTokens` schema.
	Data []byte `plist:"Data,omitempty" json:"Data,omitempty"`
	// The device's UDID (unique device identifier). The system requires this value if the
	// enrollment type is a device enrollment.
	UDID string `plist:"UDID" json:"UDID"`
	// The per-enrollment identifier for the device. The system requires this value if the
	// enrollment type is a user enrollment.
	EnrollmentID string `plist:"EnrollmentID" json:"EnrollmentID"`
	// The per-enrollment identifier for the user. The system requires this value if the
	// enrollment type is a user enrollment on the user channel.
	EnrollmentUserID string `plist:"EnrollmentUserID" json:"EnrollmentUserID"`
	// For macOS, this value is the short name of the user.
	UserShortName *string `plist:"UserShortName,omitempty" json:"UserShortName,omitempty"`
	// For macOS, this value is the ID of the user.
	UserID *string `plist:"UserID,omitempty" json:"UserID,omitempty"`
	// The full name of the user.
	UserLongName string `plist:"UserLongName" json:"UserLongName"`
}

DeclarativeManagement: Sends declarative management requests to the server.

DeclarativeManagement corresponds to mdm/checkin/declarativemanagement.yaml (Declarative Management).

func (*DeclarativeManagement) MessageTypeName

func (*DeclarativeManagement) MessageTypeName() string

MessageTypeName returns "DeclarativeManagement".

func (*DeclarativeManagement) SchemaPath

func (*DeclarativeManagement) SchemaPath() string

SchemaPath returns the Apple schema file this type was generated from.

func (*DeclarativeManagement) Validate

func (x *DeclarativeManagement) Validate(t support.Target) error

Validate checks x against the schema. With a non-zero target it also checks that every present key is supported on that OS version and enrollment context.

type Entry

type Entry struct {
	// ID is the wire identifier: RequestType, MessageType, PayloadType,
	// DeclarationType, StatusItemType, error code, or type name.
	ID string
	// Schema is the YAML path in apple/device-management.
	Schema string
	Title  string
	// New returns a zero value of the type as Message.
	New func() Message
	// NewResponse returns a zero response value, or nil when the schema
	// defines no response keys.
	NewResponse func() any
}

Entry describes one schema in the Registry.

func ByID

func ByID(id string) []Entry

ByID returns every entry with the given wire identifier, sorted by type name.

type GetBootstrapToken

type GetBootstrapToken struct {
	// The message type, which requires a value of `GetBootstrapToken`.
	MessageType string `plist:"MessageType" json:"MessageType"`
	// If `true`, the device is awaiting a `Device-Configured-Command` command before
	// proceeding through Setup Assistant.
	AwaitingConfiguration *bool `plist:"AwaitingConfiguration,omitempty" json:"AwaitingConfiguration,omitempty"`
}

GetBootstrapToken: Gets the bootstrap token from the server.

GetBootstrapToken corresponds to mdm/checkin/getbootstraptoken.yaml (Get Bootstrap Token).

func (*GetBootstrapToken) MessageTypeName

func (*GetBootstrapToken) MessageTypeName() string

MessageTypeName returns "GetBootstrapToken".

func (*GetBootstrapToken) SchemaPath

func (*GetBootstrapToken) SchemaPath() string

SchemaPath returns the Apple schema file this type was generated from.

func (*GetBootstrapToken) Validate

func (x *GetBootstrapToken) Validate(t support.Target) error

Validate checks x against the schema. With a non-zero target it also checks that every present key is supported on that OS version and enrollment context.

type GetBootstrapTokenResponse

type GetBootstrapTokenResponse struct {
	// The current bootstrap token data for the device.
	BootstrapToken []byte `plist:"BootstrapToken,omitempty" json:"BootstrapToken,omitempty"`
}

GetBootstrapTokenResponse: Response to GetBootstrapToken.

GetBootstrapTokenResponse corresponds to mdm/checkin/getbootstraptoken.yaml (Get Bootstrap Token).

func (*GetBootstrapTokenResponse) SchemaPath

func (*GetBootstrapTokenResponse) SchemaPath() string

SchemaPath returns the Apple schema file this type was generated from.

func (*GetBootstrapTokenResponse) Validate

Validate checks x against the schema. With a non-zero target it also checks that every present key is supported on that OS version and enrollment context.

type GetToken

type GetToken struct {
	// The message type, which requires a value of `GetToken`.
	MessageType string `plist:"MessageType" json:"MessageType"`
	// A string that specifies the service for the requested token.
	TokenServiceType string `plist:"TokenServiceType" json:"TokenServiceType"`
	// Parameters that the system uses to generate the token.
	TokenParameters *GetTokenTokenParameters `plist:"TokenParameters,omitempty" json:"TokenParameters,omitempty"`
	// The device's UDID (unique device identifier). The system requires this value if the
	// enrollment type is a device enrollment.
	UDID string `plist:"UDID" json:"UDID"`
	// The per-enrollment identifier for the device. The system requires this value if the
	// enrollment type is a user enrollment.
	EnrollmentID string `plist:"EnrollmentID" json:"EnrollmentID"`
	// The per-enrollment identifier for the user. The system requires this value if the
	// enrollment type is a user enrollment on the user channel.
	EnrollmentUserID string `plist:"EnrollmentUserID" json:"EnrollmentUserID"`
	// For macOS, this value is the short name of the user.
	UserShortName *string `plist:"UserShortName,omitempty" json:"UserShortName,omitempty"`
	// For macOS, this value is the ID of the user.
	UserID *string `plist:"UserID,omitempty" json:"UserID,omitempty"`
	// The full name of the user.
	UserLongName string `plist:"UserLongName" json:"UserLongName"`
}

GetToken: Gets a token from the server.

GetToken corresponds to mdm/checkin/gettoken.yaml (Get Token).

func (*GetToken) MessageTypeName

func (*GetToken) MessageTypeName() string

MessageTypeName returns "GetToken".

func (*GetToken) SchemaPath

func (*GetToken) SchemaPath() string

SchemaPath returns the Apple schema file this type was generated from.

func (*GetToken) Validate

func (x *GetToken) Validate(t support.Target) error

Validate checks x against the schema. With a non-zero target it also checks that every present key is supported on that OS version and enrollment context.

type GetTokenResponse

type GetTokenResponse struct {
	// The token data. If the token is a string value, it needs to be a UTF-8-encoded string.
	TokenData []byte `plist:"TokenData,omitempty" json:"TokenData,omitempty"`
}

GetTokenResponse: Response to GetToken.

GetTokenResponse corresponds to mdm/checkin/gettoken.yaml (Get Token).

func (*GetTokenResponse) SchemaPath

func (*GetTokenResponse) SchemaPath() string

SchemaPath returns the Apple schema file this type was generated from.

func (*GetTokenResponse) Validate

func (x *GetTokenResponse) Validate(t support.Target) error

Validate checks x against the schema. With a non-zero target it also checks that every present key is supported on that OS version and enrollment context.

type GetTokenTokenParameters

type GetTokenTokenParameters struct {
	// A security token to generate the server token. Required by the `com.apple.watch.pairing`
	// service type.
	SecurityToken *string `plist:"SecurityToken,omitempty" json:"SecurityToken,omitempty"`
	// The identifier of the phone paired to the watch. Required by the
	// `com.apple.watch.pairing` service type.
	PhoneUDID *string `plist:"PhoneUDID,omitempty" json:"PhoneUDID,omitempty"`
	// The identifier of the watch paired to the phone. Required by the
	// `com.apple.watch.pairing` service type.
	WatchUDID *string `plist:"WatchUDID,omitempty" json:"WatchUDID,omitempty"`
}

GetTokenTokenParameters: Parameters that the system uses to generate the token.

type Message

type Message interface {
	// MessageTypeName returns the wire identifier from Apple's schema.
	MessageTypeName() string
	// SchemaPath returns the schema file the type was generated from.
	SchemaPath() string
	// Validate checks the value against the schema for the target.
	Validate(t support.Target) error
}

Message is implemented by every top-level type in this package.

type ReturnToService

type ReturnToService struct {
	// The message type, which requires a value of `ReturnToService`.
	MessageType string `plist:"MessageType" json:"MessageType"`
	// The device's UDID (unique device identifier). The system requires this value if the
	// enrollment type is a device enrollment.
	UDID string `plist:"UDID" json:"UDID"`
}

ReturnToService: Gets the return-to-service configuration from the server.

ReturnToService corresponds to mdm/checkin/returntoservice.yaml (Return To Service).

func (*ReturnToService) MessageTypeName

func (*ReturnToService) MessageTypeName() string

MessageTypeName returns "ReturnToService".

func (*ReturnToService) SchemaPath

func (*ReturnToService) SchemaPath() string

SchemaPath returns the Apple schema file this type was generated from.

func (*ReturnToService) Validate

func (x *ReturnToService) Validate(t support.Target) error

Validate checks x against the schema. With a non-zero target it also checks that every present key is supported on that OS version and enrollment context.

type ReturnToServiceResponse

type ReturnToServiceResponse struct {
	// If `true`, the device preserves the data plan on an iPhone or iPad with eSIM
	// functionality, if one exists. This value is available in iOS 26.4 and later.
	PreserveDataPlan *bool `plist:"PreserveDataPlan,omitempty" json:"PreserveDataPlan,omitempty"`
	// A dictionary containing the configuration for return to service.
	ReturnToService ReturnToServiceResponseReturnToService `plist:"ReturnToService,omitempty" json:"ReturnToService,omitempty"`
}

ReturnToServiceResponse: Response to ReturnToService.

ReturnToServiceResponse corresponds to mdm/checkin/returntoservice.yaml (Return To Service).

func (*ReturnToServiceResponse) SchemaPath

func (*ReturnToServiceResponse) SchemaPath() string

SchemaPath returns the Apple schema file this type was generated from.

func (*ReturnToServiceResponse) Validate

Validate checks x against the schema. With a non-zero target it also checks that every present key is supported on that OS version and enrollment context.

type ReturnToServiceResponseReturnToService

type ReturnToServiceResponseReturnToService struct {
	// If `true`, the device automatically erases itself and then performs reenrollment.
	Enabled bool `plist:"Enabled" json:"Enabled"`
	// The Wi-Fi profile that installs after erasure when using return to service. This is
	// required when the device doesn't have Ethernet access.
	WiFiProfileData []byte `plist:"WiFiProfileData,omitempty" json:"WiFiProfileData,omitempty"`
	// The MDM profile that installs after erasure when using return to service. If provided,
	// the device uses this profile directly instead of fetching it from the server. This key
	// is required if the device's Automated Device Enrollment profile contains the
	// `configuration-web-url` key.
	MDMProfileData []byte `plist:"MDMProfileData,omitempty" json:"MDMProfileData,omitempty"`
	// The system uses the bootstrap token for return to service with app preservation.
	// Required when Automated Device Enrollment enables return to service for the device.
	BootstrapToken []byte `plist:"BootstrapToken,omitempty" json:"BootstrapToken,omitempty"`
}

ReturnToServiceResponseReturnToService: A dictionary containing the configuration for return to service.

type SetBootstrapToken

type SetBootstrapToken struct {
	// The message type, which requires a value of `SetBootstrapToken`.
	MessageType string `plist:"MessageType" json:"MessageType"`
	// The device's bootstrap token data. If this field is missing or zero length, the server
	// needs to remove the bootstrap token for this device.
	BootstrapToken []byte `plist:"BootstrapToken,omitempty" json:"BootstrapToken,omitempty"`
	// If `true`, the device is awaiting a `Device-Configured-Command` command before
	// proceeding through Setup Assistant.
	AwaitingConfiguration *bool `plist:"AwaitingConfiguration,omitempty" json:"AwaitingConfiguration,omitempty"`
}

SetBootstrapToken: Sends the bootstrap token to the server.

SetBootstrapToken corresponds to mdm/checkin/setbootstraptoken.yaml (Set Bootstrap Token).

func (*SetBootstrapToken) MessageTypeName

func (*SetBootstrapToken) MessageTypeName() string

MessageTypeName returns "SetBootstrapToken".

func (*SetBootstrapToken) SchemaPath

func (*SetBootstrapToken) SchemaPath() string

SchemaPath returns the Apple schema file this type was generated from.

func (*SetBootstrapToken) Validate

func (x *SetBootstrapToken) Validate(t support.Target) error

Validate checks x against the schema. With a non-zero target it also checks that every present key is supported on that OS version and enrollment context.

type TokenUpdate

type TokenUpdate struct {
	// If `true`, the device isn't on-console.
	NotOnConsole bool `plist:"NotOnConsole" json:"NotOnConsole"`
	// The message type, which requires a value of `TokenUpdate`.
	MessageType string `plist:"MessageType" json:"MessageType"`
	// The topic the device subscribes to.
	Topic string `plist:"Topic" json:"Topic"`
	// The device's UDID (unique device identifier). The system requires this value if the
	// enrollment type is a device enrollment.
	UDID string `plist:"UDID" json:"UDID"`
	// The per-enrollment identifier for the device. The system requires this value if the
	// enrollment type is a user enrollment.
	EnrollmentID string `plist:"EnrollmentID" json:"EnrollmentID"`
	// The per-enrollment identifier for the user. The system requires this value if the
	// enrollment type is a user enrollment on the user channel.
	EnrollmentUserID string `plist:"EnrollmentUserID" json:"EnrollmentUserID"`
	// For macOS, this value is the short name of the user.
	UserShortName *string `plist:"UserShortName,omitempty" json:"UserShortName,omitempty"`
	// For macOS, this value is the ID of the user.
	UserID *string `plist:"UserID,omitempty" json:"UserID,omitempty"`
	// The full name of the user.
	UserLongName string `plist:"UserLongName" json:"UserLongName"`
	// The push token for the device.
	Token []byte `plist:"Token,omitempty" json:"Token,omitempty"`
	// The magic string to include in the push notification message.
	PushMagic string `plist:"PushMagic" json:"PushMagic"`
	// The data to use to unlock the device. If provided, the server needs to retain this data
	// and send it when trying to implement `Clear-Passcode-Command`.
	UnlockToken []byte `plist:"UnlockToken,omitempty" json:"UnlockToken,omitempty"`
	// If `true` from the device channel, the device is awaiting a `Device-Configured-Command`
	// command before proceeding through Setup Assistant.
	AwaitingConfiguration *bool `plist:"AwaitingConfiguration,omitempty" json:"AwaitingConfiguration,omitempty"`
}

TokenUpdate: Updates the token for a device on the server.

TokenUpdate corresponds to mdm/checkin/tokenupdate.yaml (Token Update).

func (*TokenUpdate) MessageTypeName

func (*TokenUpdate) MessageTypeName() string

MessageTypeName returns "TokenUpdate".

func (*TokenUpdate) SchemaPath

func (*TokenUpdate) SchemaPath() string

SchemaPath returns the Apple schema file this type was generated from.

func (*TokenUpdate) Validate

func (x *TokenUpdate) Validate(t support.Target) error

Validate checks x against the schema. With a non-zero target it also checks that every present key is supported on that OS version and enrollment context.

type UserAuthenticate

type UserAuthenticate struct {
	// The message type, which requires a value of `UserAuthenticate`.
	MessageType string `plist:"MessageType" json:"MessageType"`
	// The device's UDID (unique device identifier). The system requires this value if the
	// enrollment type is a device enrollment.
	UDID string `plist:"UDID" json:"UDID"`
	// The local mobile user's GUID or the network user's GUID from an Open Directory record.
	UserID string `plist:"UserID" json:"UserID"`
	// A string that the client provides in the second `User-Authenticate` request after
	// receiving `DigestChallenge` from the server on the first `User-Authenticate` request.
	DigestResponse string `plist:"DigestResponse" json:"DigestResponse"`
}

UserAuthenticate: Authenticates a user with a two-step authentication protocol.

UserAuthenticate corresponds to mdm/checkin/userauthenticate.yaml (User Authenticate).

func (*UserAuthenticate) MessageTypeName

func (*UserAuthenticate) MessageTypeName() string

MessageTypeName returns "UserAuthenticate".

func (*UserAuthenticate) SchemaPath

func (*UserAuthenticate) SchemaPath() string

SchemaPath returns the Apple schema file this type was generated from.

func (*UserAuthenticate) Validate

func (x *UserAuthenticate) Validate(t support.Target) error

Validate checks x against the schema. With a non-zero target it also checks that every present key is supported on that OS version and enrollment context.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL